startx 0.9.9 → 1.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/apps/cli/package.json +5 -1
- package/apps/cli/src/commands/common/test.ts +11 -0
- package/apps/cli/src/commands/index.ts +2 -1
- package/apps/cli/tsconfig.json +1 -0
- package/apps/core-server/tsconfig.json +1 -0
- package/apps/queue-worker/Dockerfile +35 -0
- package/apps/queue-worker/eslint.config.ts +7 -0
- package/apps/queue-worker/package.json +57 -0
- package/apps/queue-worker/src/bullmq/worker.ts +25 -0
- package/apps/queue-worker/src/index.ts +3 -0
- package/apps/queue-worker/tsconfig.json +10 -0
- package/apps/queue-worker/tsdown.config.ts +15 -0
- package/apps/queue-worker/vitest.config.ts +3 -0
- package/apps/startx-cli/dist/index.mjs +2 -2
- package/apps/startx-cli/src/commands/init.ts +2 -1
- package/apps/startx-cli/src/utils/cli-utils.ts +3 -1
- package/package.json +2 -1
- package/packages/@repo/lib/src/mail-module/nodemailer.ts +34 -20
- package/packages/@repo/lib/src/otp-module/index.ts +6 -1
- package/packages/@repo/redis/src/index.ts +1 -0
- package/packages/@repo/redis/src/lib/redis-client.ts +5 -3
- package/packages/aix/src/aix.ts +14 -4
- package/packages/aix/src/providers/ai-interface.ts +2 -3
- package/packages/aix/src/providers/openai/openai.ts +1 -0
- package/packages/queue/eslint.config.ts +4 -0
- package/packages/queue/package.json +50 -0
- package/packages/queue/src/adapter/bullmq-adapter.ts +122 -0
- package/packages/queue/src/common/email-queue.ts +23 -0
- package/packages/queue/src/common/index.ts +5 -0
- package/packages/queue/src/index.ts +5 -0
- package/packages/queue/src/queue-interface.ts +33 -0
- package/packages/queue/src/registry.ts +13 -0
- package/packages/queue/src/types.ts +24 -0
- package/packages/queue/tsconfig.json +7 -0
- package/packages/queue/vitest.config.ts +3 -0
- package/pnpm-workspace.yaml +4 -1
- package/startx.json +2 -2
package/apps/cli/package.json
CHANGED
|
@@ -29,8 +29,12 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@inquirer/prompts": "^8.3.0",
|
|
31
31
|
"@repo/logger": "workspace:*",
|
|
32
|
+
"@repo/mail": "workspace:*",
|
|
32
33
|
"@repo/lib": "workspace:*",
|
|
33
|
-
"
|
|
34
|
+
"@repo/env": "workspace:*",
|
|
35
|
+
"commander": "^14.0.0",
|
|
36
|
+
"@repo/queue": "workspace:*",
|
|
37
|
+
"aix": "workspace:*"
|
|
34
38
|
},
|
|
35
39
|
"startx": {
|
|
36
40
|
"gTags": [
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { logger } from "@repo/logger";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { ICommand } from "../i-command.js";
|
|
4
|
+
|
|
5
|
+
export class TestCommand extends ICommand {
|
|
6
|
+
command = new Command("test").description("For general testing purposes.").action(this.run.bind(this));
|
|
7
|
+
|
|
8
|
+
run() {
|
|
9
|
+
logger.info("Test command executed.");
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { HashingCommands } from "./common/hashing.js";
|
|
2
2
|
import { PingCommand } from "./common/ping.js";
|
|
3
3
|
import { RandomCommand } from "./common/random.js";
|
|
4
|
+
import { TestCommand } from "./common/test.js";
|
|
4
5
|
import { ICommand } from "./i-command.js";
|
|
5
6
|
|
|
6
|
-
export const commands: ICommand[] = [new PingCommand(), new RandomCommand(), ...HashingCommands];
|
|
7
|
+
export const commands: ICommand[] = [new PingCommand(), new RandomCommand(), new TestCommand(), ...HashingCommands];
|
package/apps/cli/tsconfig.json
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
FROM node:24-alpine AS base
|
|
2
|
+
RUN apk add --no-cache git \
|
|
3
|
+
&& corepack enable \
|
|
4
|
+
&& corepack prepare pnpm@latest --activate
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
FROM base AS builder
|
|
8
|
+
|
|
9
|
+
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
10
|
+
|
|
11
|
+
COPY --parents apps/*/package.json ./
|
|
12
|
+
COPY --parents packages/*/package.json ./
|
|
13
|
+
COPY --parents configs/*/package.json ./
|
|
14
|
+
|
|
15
|
+
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
|
|
16
|
+
pnpm install --frozen-lockfile
|
|
17
|
+
|
|
18
|
+
COPY apps/bullmq-worker/ ./apps/bullmq-worker/
|
|
19
|
+
COPY packages ./packages
|
|
20
|
+
COPY configs ./configs
|
|
21
|
+
COPY turbo.json ./
|
|
22
|
+
|
|
23
|
+
# Build the required packages
|
|
24
|
+
RUN pnpm build:web
|
|
25
|
+
|
|
26
|
+
# --- Final production image ---
|
|
27
|
+
FROM node:24-alpine
|
|
28
|
+
|
|
29
|
+
WORKDIR /app
|
|
30
|
+
|
|
31
|
+
# Copy built server dist
|
|
32
|
+
COPY --from=builder /app/apps/bullmq-worker/dist ./
|
|
33
|
+
EXPOSE 3000
|
|
34
|
+
|
|
35
|
+
CMD ["node", "./index.mjs"]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "queue-worker",
|
|
3
|
+
"description": "",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsx watch src/index.ts",
|
|
8
|
+
"dev:debug": "tsx watch --inspect src/index.ts",
|
|
9
|
+
"bun:dev": "bun --watch src/index.ts",
|
|
10
|
+
"build": "tsdown --config-loader unrun",
|
|
11
|
+
"start": "node dist/index.mjs",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . src/**/*.ts --fix",
|
|
14
|
+
"clean": "rimraf dist .turbo dist",
|
|
15
|
+
"deep:clean": "rimraf node_modules dist .turbo",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"format": "biome format --write .",
|
|
18
|
+
"format:check": "biome ci .",
|
|
19
|
+
"test": "vitest run"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"constants": "workspace:^",
|
|
23
|
+
"@db/drizzle": "workspace:^",
|
|
24
|
+
"@repo/mail": "workspace:^",
|
|
25
|
+
"@repo/lib": "workspace:^",
|
|
26
|
+
"@repo/redis": "workspace:^",
|
|
27
|
+
"@repo/env": "workspace:^",
|
|
28
|
+
"@repo/logger": "workspace:^",
|
|
29
|
+
"@repo/queue": "workspace:*"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"eslint-config": "workspace:*",
|
|
33
|
+
"vitest-config": "workspace:*",
|
|
34
|
+
"tsdown-config": "workspace:*",
|
|
35
|
+
"typescript-config": "workspace:*"
|
|
36
|
+
},
|
|
37
|
+
"startx": {
|
|
38
|
+
"gTags": [
|
|
39
|
+
"node",
|
|
40
|
+
"backend"
|
|
41
|
+
],
|
|
42
|
+
"tags": [
|
|
43
|
+
"express"
|
|
44
|
+
],
|
|
45
|
+
"requiredDeps": [
|
|
46
|
+
"@repo/env",
|
|
47
|
+
"@repo/logger",
|
|
48
|
+
"@repo/lib",
|
|
49
|
+
"@repo/redis",
|
|
50
|
+
"@repo/queue"
|
|
51
|
+
],
|
|
52
|
+
"requiredDevDeps": [
|
|
53
|
+
"typescript-config",
|
|
54
|
+
"tsdown-config"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SMTPMailService } from "@repo/lib/mail-module";
|
|
2
|
+
import { logger } from "@repo/logger";
|
|
3
|
+
import { BullQueue } from "@repo/queue";
|
|
4
|
+
export const bullWorker = () => {
|
|
5
|
+
logger.info("Starting BullMQ worker...");
|
|
6
|
+
|
|
7
|
+
BullQueue.registerWorker(
|
|
8
|
+
"email-send",
|
|
9
|
+
async data => {
|
|
10
|
+
const message = await SMTPMailService.sendMail({
|
|
11
|
+
subject: data.subject,
|
|
12
|
+
text: data.text!,
|
|
13
|
+
to: data.to,
|
|
14
|
+
html: data.html,
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
messageId: message.messageId,
|
|
18
|
+
success: true,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
concurrency: 10,
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineConfig } from "tsdown";
|
|
2
|
+
import { baseConfig } from "tsdown-config";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
...baseConfig,
|
|
6
|
+
platform: "node",
|
|
7
|
+
external: ["sharp"],
|
|
8
|
+
noExternal: [/(.*)/],
|
|
9
|
+
clean: false,
|
|
10
|
+
outputOptions: {
|
|
11
|
+
codeSplitting: false,
|
|
12
|
+
preserveModules: false,
|
|
13
|
+
legalComments: "none",
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -184,7 +184,7 @@ $&`).replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g,`$1$2`).replace(/\
|
|
|
184
184
|
`)+1;for(;e!==0;)this.onNewLine(this.offset+e),e=this.source.indexOf(`
|
|
185
185
|
`,e)+1}yield*this.pop();break;default:yield*this.pop(),yield*this.step()}}*blockMap(e){let t=e.items[e.items.length-1];switch(this.type){case`newline`:if(this.onKeyLine=!1,t.value){let n=`end`in t.value?t.value.end:void 0;(Array.isArray(n)?n[n.length-1]:void 0)?.type===`comment`?n?.push(this.sourceToken):e.items.push({start:[this.sourceToken]})}else t.sep?t.sep.push(this.sourceToken):t.start.push(this.sourceToken);return;case`space`:case`comment`:if(t.value)e.items.push({start:[this.sourceToken]});else if(t.sep)t.sep.push(this.sourceToken);else{if(this.atIndentedComment(t.start,e.indent)){let n=e.items[e.items.length-2]?.value?.end;if(Array.isArray(n)){Array.prototype.push.apply(n,t.start),n.push(this.sourceToken),e.items.pop();return}}t.start.push(this.sourceToken)}return}if(this.indent>=e.indent){let n=!this.onKeyLine&&this.indent===e.indent,r=n&&(t.sep||t.explicitKey)&&this.type!==`seq-item-ind`,a=[];if(r&&t.sep&&!t.value){let n=[];for(let r=0;r<t.sep.length;++r){let i=t.sep[r];switch(i.type){case`newline`:n.push(r);break;case`space`:break;case`comment`:i.indent>e.indent&&(n.length=0);break;default:n.length=0}}n.length>=2&&(a=t.sep.splice(n[1]))}switch(this.type){case`anchor`:case`tag`:r||t.value?(a.push(this.sourceToken),e.items.push({start:a}),this.onKeyLine=!0):t.sep?t.sep.push(this.sourceToken):t.start.push(this.sourceToken);return;case`explicit-key-ind`:!t.sep&&!t.explicitKey?(t.start.push(this.sourceToken),t.explicitKey=!0):r||t.value?(a.push(this.sourceToken),e.items.push({start:a,explicitKey:!0})):this.stack.push({type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken],explicitKey:!0}]}),this.onKeyLine=!0;return;case`map-value-ind`:if(t.explicitKey)if(!t.sep)if(i(t.start,`newline`))Object.assign(t,{key:null,sep:[this.sourceToken]});else{let e=c(t.start);this.stack.push({type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:e,key:null,sep:[this.sourceToken]}]})}else if(t.value)e.items.push({start:[],key:null,sep:[this.sourceToken]});else if(i(t.sep,`map-value-ind`))this.stack.push({type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:a,key:null,sep:[this.sourceToken]}]});else if(o(t.key)&&!i(t.sep,`newline`)){let e=c(t.start),n=t.key,r=t.sep;r.push(this.sourceToken),delete t.key,delete t.sep,this.stack.push({type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:e,key:n,sep:r}]})}else a.length>0?t.sep=t.sep.concat(a,this.sourceToken):t.sep.push(this.sourceToken);else t.sep?t.value||r?e.items.push({start:a,key:null,sep:[this.sourceToken]}):i(t.sep,`map-value-ind`)?this.stack.push({type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:[],key:null,sep:[this.sourceToken]}]}):t.sep.push(this.sourceToken):Object.assign(t,{key:null,sep:[this.sourceToken]});this.onKeyLine=!0;return;case`alias`:case`scalar`:case`single-quoted-scalar`:case`double-quoted-scalar`:{let n=this.flowScalar(this.type);r||t.value?(e.items.push({start:a,key:n,sep:[]}),this.onKeyLine=!0):t.sep?this.stack.push(n):(Object.assign(t,{key:n,sep:[]}),this.onKeyLine=!0);return}default:{let r=this.startBlockValue(e);if(r){if(r.type===`block-seq`){if(!t.explicitKey&&t.sep&&!i(t.sep,`newline`)){yield*this.pop({type:`error`,offset:this.offset,message:`Unexpected block-seq-ind on same line with key`,source:this.source});return}}else n&&e.items.push({start:a});this.stack.push(r);return}}}}yield*this.pop(),yield*this.step()}*blockSequence(e){let t=e.items[e.items.length-1];switch(this.type){case`newline`:if(t.value){let n=`end`in t.value?t.value.end:void 0;(Array.isArray(n)?n[n.length-1]:void 0)?.type===`comment`?n?.push(this.sourceToken):e.items.push({start:[this.sourceToken]})}else t.start.push(this.sourceToken);return;case`space`:case`comment`:if(t.value)e.items.push({start:[this.sourceToken]});else{if(this.atIndentedComment(t.start,e.indent)){let n=e.items[e.items.length-2]?.value?.end;if(Array.isArray(n)){Array.prototype.push.apply(n,t.start),n.push(this.sourceToken),e.items.pop();return}}t.start.push(this.sourceToken)}return;case`anchor`:case`tag`:if(t.value||this.indent<=e.indent)break;t.start.push(this.sourceToken);return;case`seq-item-ind`:if(this.indent!==e.indent)break;t.value||i(t.start,`seq-item-ind`)?e.items.push({start:[this.sourceToken]}):t.start.push(this.sourceToken);return}if(this.indent>e.indent){let t=this.startBlockValue(e);if(t){this.stack.push(t);return}}yield*this.pop(),yield*this.step()}*flowCollection(e){let t=e.items[e.items.length-1];if(this.type===`flow-error-end`){let e;do yield*this.pop(),e=this.peek(1);while(e?.type===`flow-collection`)}else if(e.end.length===0){switch(this.type){case`comma`:case`explicit-key-ind`:!t||t.sep?e.items.push({start:[this.sourceToken]}):t.start.push(this.sourceToken);return;case`map-value-ind`:!t||t.value?e.items.push({start:[],key:null,sep:[this.sourceToken]}):t.sep?t.sep.push(this.sourceToken):Object.assign(t,{key:null,sep:[this.sourceToken]});return;case`space`:case`comment`:case`newline`:case`anchor`:case`tag`:!t||t.value?e.items.push({start:[this.sourceToken]}):t.sep?t.sep.push(this.sourceToken):t.start.push(this.sourceToken);return;case`alias`:case`scalar`:case`single-quoted-scalar`:case`double-quoted-scalar`:{let n=this.flowScalar(this.type);!t||t.value?e.items.push({start:[],key:n,sep:[]}):t.sep?this.stack.push(n):Object.assign(t,{key:n,sep:[]});return}case`flow-map-end`:case`flow-seq-end`:e.end.push(this.sourceToken);return}let n=this.startBlockValue(e);n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{let t=this.peek(2);if(t.type===`block-map`&&(this.type===`map-value-ind`&&t.indent===e.indent||this.type===`newline`&&!t.items[t.items.length-1].sep))yield*this.pop(),yield*this.step();else if(this.type===`map-value-ind`&&t.type!==`flow-collection`){let n=c(s(t));l(e);let r=e.end.splice(1,e.end.length);r.push(this.sourceToken);let i={type:`block-map`,offset:e.offset,indent:e.indent,items:[{start:n,key:e,sep:r}]};this.onKeyLine=!0,this.stack[this.stack.length-1]=i}else yield*this.lineEnd(e)}}flowScalar(e){if(this.onNewLine){let e=this.source.indexOf(`
|
|
186
186
|
`)+1;for(;e!==0;)this.onNewLine(this.offset+e),e=this.source.indexOf(`
|
|
187
|
-
`,e)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case`alias`:case`scalar`:case`single-quoted-scalar`:case`double-quoted-scalar`:return this.flowScalar(this.type);case`block-scalar-header`:return{type:`block-scalar`,offset:this.offset,indent:this.indent,props:[this.sourceToken],source:``};case`flow-map-start`:case`flow-seq-start`:return{type:`flow-collection`,offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case`seq-item-ind`:return{type:`block-seq`,offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case`explicit-key-ind`:{this.onKeyLine=!0;let t=c(s(e));return t.push(this.sourceToken),{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,explicitKey:!0}]}}case`map-value-ind`:{this.onKeyLine=!0;let t=c(s(e));return{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,t){return this.type!==`comment`||this.indent<=t?!1:e.every(e=>e.type===`newline`||e.type===`space`)}*documentEnd(e){this.type!==`doc-mode`&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case`comma`:case`doc-start`:case`doc-end`:case`flow-seq-end`:case`flow-map-end`:case`map-value-ind`:yield*this.pop(),yield*this.step();break;case`newline`:this.onKeyLine=!1;default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop())}}}})),I_=_((e=>{var t=O_(),n=d_(),r=f_(),i=Ig(),a=X(),o=P_(),s=F_();function c(e){let t=e.prettyErrors!==!1;return{lineCounter:e.lineCounter||t&&new o.LineCounter||null,prettyErrors:t}}function l(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=Array.from(l.compose(o.parse(e)));if(a&&i)for(let t of u)t.errors.forEach(r.prettifyError(e,i)),t.warnings.forEach(r.prettifyError(e,i));return u.length>0?u:Object.assign([],{empty:!0},l.streamInfo())}function u(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=null;for(let t of l.compose(o.parse(e),!0,e.length))if(!u)u=t;else if(u.options.logLevel!==`silent`){u.errors.push(new r.YAMLParseError(t.range.slice(0,2),`MULTIPLE_DOCS`,`Source contains multiple documents; please use YAML.parseAllDocuments()`));break}return a&&i&&(u.errors.forEach(r.prettifyError(e,i)),u.warnings.forEach(r.prettifyError(e,i))),u}function d(e,t,n){let r;typeof t==`function`?r=t:n===void 0&&t&&typeof t==`object`&&(n=t);let a=u(e,n);if(!a)return null;if(a.warnings.forEach(e=>i.warn(a.options.logLevel,e)),a.errors.length>0){if(a.options.logLevel!==`silent`)throw a.errors[0];a.errors=[]}return a.toJS(Object.assign({reviver:r},n))}function f(e,t,r){let i=null;if(typeof t==`function`||Array.isArray(t)?i=t:r===void 0&&t&&(r=t),typeof r==`string`&&(r=r.length),typeof r==`number`){let e=Math.round(r);r=e<1?void 0:e>8?{indent:8}:{indent:e}}if(e===void 0){let{keepUndefined:e}=r??t??{};if(!e)return}return a.isDocument(e)&&!i?e.toString(r):new n.Document(e,i,r).toString(r)}e.parse=d,e.parseAllDocuments=l,e.parseDocument=u,e.stringify=f})),L_=b(_((e=>{var t=O_(),n=d_(),r=l_(),i=f_(),a=Og(),o=X(),s=zg(),c=Z(),l=Vg(),u=Ug();M_();var d=N_(),f=P_(),p=F_(),m=I_(),h=Sg();e.Composer=t.Composer,e.Document=n.Document,e.Schema=r.Schema,e.YAMLError=i.YAMLError,e.YAMLParseError=i.YAMLParseError,e.YAMLWarning=i.YAMLWarning,e.Alias=a.Alias,e.isAlias=o.isAlias,e.isCollection=o.isCollection,e.isDocument=o.isDocument,e.isMap=o.isMap,e.isNode=o.isNode,e.isPair=o.isPair,e.isScalar=o.isScalar,e.isSeq=o.isSeq,e.Pair=s.Pair,e.Scalar=c.Scalar,e.YAMLMap=l.YAMLMap,e.YAMLSeq=u.YAMLSeq,e.Lexer=d.Lexer,e.LineCounter=f.LineCounter,e.Parser=p.Parser,e.parse=m.parse,e.parseAllDocuments=m.parseAllDocuments,e.parseDocument=m.parseDocument,e.stringify=m.stringify,e.visit=h.visit,e.visitAsync=h.visitAsync}))(),1);function R_(){return nm.NODE_ENV===`development`?t.resolve(process.cwd(),`../../`):process.cwd()}const z_=new class{root=R_();async pathExists(e){try{return await a.access(e),!0}catch{return!1}}async writeFile({file:e,content:n}){await a.writeFile(t.resolve(this.root,e),n)}async writeJSONFile({file:e,content:n,dir:r}){e=`${e}.json`;let i=t.resolve(this.root,e);if(r){let n=t.resolve(this.root,r);await this.ensurePathExists({dir:r}),i=t.resolve(n,e)}await a.writeFile(i,JSON.stringify(n,null,2))}async readFile({file:e}){return await a.readFile(t.resolve(this.root,e),`utf-8`)}async readJSONFile({file:e,dir:n}){try{e=`${e}.json`;let r=t.resolve(this.root,n??``,e),i=await a.readFile(r,`utf-8`);return JSON.parse(i)}catch(t){return console.error(`Failed to read JSON file at ${e}:`,t),null}}async readYamlFile({file:e,dir:n}){try{e=`${e}.yaml`;let r=t.resolve(this.root,n??``,e),i=await a.readFile(r,`utf-8`);return L_.parseDocument(i)}catch(t){return console.error(`Failed to read Yaml file at ${e}:`,t),null}}async ensurePathExists({dir:e}){let n=t.resolve(this.root,e);await this.pathExists(n)||await a.mkdir(n,{recursive:!0})}async avoidOverriding({file:e}){let n=t.resolve(this.root,e);if(await this.pathExists(n))throw Error(`File ${n} already exists`)}async removeFile({file:e}){let n=t.resolve(this.root,e);await this.pathExists(n)&&await a.unlink(n)}async removeDirectory({dir:e,target:n}){let r=t.resolve(this.root,e,n);await this.pathExists(r)&&await a.rm(r,{recursive:!0,force:!0})}async copyFile({from:e,to:n}){await this.ensurePathExists({dir:t.dirname(n)}),await a.copyFile(t.resolve(this.root,e),t.resolve(this.root,n))}async copyDirectory({from:e,to:n,recursive:r=!0,include:i,exclude:o}){let s=t.resolve(this.root,e),c=t.resolve(this.root,n);if(!await this.pathExists(s))return;await this.ensurePathExists({dir:t.join(n)});let l=await a.readdir(s,{withFileTypes:!0});for(let u of l){let l=t.join(s,u.name),d=t.join(c,u.name),f=(!i||i.test(u.name))&&(!o||!o.test(u.name));u.isDirectory()?r&&await this.copyDirectory({from:t.join(e,u.name),to:t.join(n,u.name),recursive:r,include:i,exclude:o}):u.isFile()&&f&&await a.copyFile(l,d)}}async listDirectories({dir:e}){try{return(await a.readdir(t.resolve(this.root,e),{withFileTypes:!0})).filter(e=>e.isDirectory()).map(e=>e.name)}catch(t){return console.error(`Error listing directories in ${e}:`,t),[]}}async listFiles({dir:e}){try{return(await a.readdir(t.resolve(this.root,e),{withFileTypes:!0})).filter(e=>e.isFile()).map(e=>e.name)}catch(t){return console.error(`Error listing files in ${e}:`,t),[]}}},B_={"startx.json":{tags:[`never`]},".npmignore":{tags:[`never`]},".npmrc":{tags:[`never`]},".prettier.cjs":{tags:[`prettier`]},".prettierignore":{tags:[`biome`]},"biome.json":{tags:[`biome`]},"pnpm-lock.yaml":{tags:[`never`]},"pnpm-workspace.yaml":{tags:[`root`]},"turbo.json":{tags:[`root`]},LICENSE:{tags:[`never`]},".env":{tags:[`never`]},"tsdown.config.ts":{tags:[`tsdown`]},"eslint.config.ts":{tags:[`eslint`,`node`]},"vitest.config.ts":{tags:[`vitest`,`node`]},"package.json":{tags:[`never`]}},V_=tm({STARTX_ENV:Gp.enum([`development`,`production`,`test`,`staging`]).default(`production`)});var H_=class{static getDirectory(){let e=n(import.meta.url),r=t.dirname(e),i=process.cwd();return r=V_.STARTX_ENV===`development`?t.resolve(r,`../../../../`):t.resolve(r,`../../../`),{template:r,workspace:i}}static async getPackageList(){let e=this.getDirectory().template,n=async(n,r,i=``,a)=>{let o=t.join(e,...n.split(`/`));try{let n=await z_.listDirectories({dir:o});return a&&(n=n.filter(a)),(await Promise.all(n.map(async n=>{let a=t.join(o,n),s=t.relative(e,a),c=i?`${i}${n}`:n,l;try{l=await this.parsePackageJson({dir:a})}catch{l=null}return l?{type:r,path:a,relativePath:s,name:c,packageJson:l}:(console.error(`Ignoring this package failed to read package.json: ${c}`),null)}))).filter(e=>e!==null)}catch(e){return console.error(`Error reading directory ${o}:`,e),[]}};return(await Promise.all([n(`apps`,`apps`),n(`configs`,`configs`),n(`packages`,`packages`,``,e=>e!==`@repo`),n(`packages/@repo`,`packages`,`@repo/`)])).flat()}static async parsePackageJson({dir:e,file:t=`package`}){return await z_.readJSONFile({dir:e,file:t})}static async parsePnpmWorkspace({dir:e}){return(await z_.readYamlFile({file:`pnpm-workspace`,dir:e}))?.toJSON()}};const U_={"@biomejs/biome":{tags:[`node`,`biome`,`root`],version:`catalog:`,isDevDependency:!0},prettier:{tags:[`node`,`prettier`,`root`],version:`catalog:`,isDevDependency:!0},eslint:{tags:[`node`,`eslint`,`root`],version:`catalog:`,isDevDependency:!0},vitest:{tags:[`node`,`vitest`,`root`],version:`catalog:`,isDevDependency:!0},tsdown:{isDevDependency:!0,tags:[`node`,`tsdown`,`root`],version:`catalog:`},"tsdown-config":{tags:[`node`,`tsdown`,`runnable`],version:`workspace:^`,isDevDependency:!0},"@types/node":{tags:[`node`,`root`],version:`catalog:`,isDevDependency:!0},"typescript-config":{tags:[`node`],version:`workspace:^`,isDevDependency:!0},"eslint-config":{tags:[`node`,`eslint`],version:`workspace:^`,isDevDependency:!0},"vitest-config":{tags:[`node`,`vitest`],version:`workspace:^`,isDevDependency:!0}},W_={dev:[{script:`turbo run dev`,tags:[`runnable`,`root`]},{script:`tsx watch src/index.ts`,tags:[`runnable`,`node`,`backend`,`express`]},{script:`email dev --port 3014 --dir ./src`,tags:[`node`,`mail`]}],"dev:debug":[{script:`turbo run dev:debug`,tags:[`node`,`runnable`,`root`]},{script:`tsx watch --inspect src/index.ts`,tags:[`backend`,`node`,`runnable`,`express`]}],"bun:dev":[{script:`turbo run bun:dev`,tags:[`node`,`runnable`,`root`]},{script:`bun --watch src/index.ts`,tags:[`backend`,`node`,`runnable`,`express`]}],build:[{script:`turbo run build`,tags:[`runnable`,`root`]},{script:`tsdown --config-loader unrun`,tags:[`runnable`,`node`,`tsdown`]}],cli:[{script:`turbo run cli -- `,tags:[`runnable`,`node`,`cli`,`root`]},{script:`tsx src/index.ts`,tags:[`runnable`,`node`,`cli`,`commander`]}],start:[{script:`turbo run start`,tags:[`backend`,`runnable`,`node`,`root`]},{script:`node dist/index.mjs`,tags:[`node`,`runnable`]}],lint:[{script:`turbo run lint`,tags:[`node`,`eslint`,`root`]},{script:`eslint .`,tags:[`node`,`eslint`]}],"lint:fix":[{script:`turbo run lint:fix`,tags:[`node`,`eslint`,`root`]},{script:`eslint . src/**/*.ts --fix`,tags:[`node`,`eslint`]}],clean:[{script:`turbo run clean`,tags:[`root`]},{script:`rimraf dist .turbo dist`,tags:[]}],"deep:clean":[{script:`turbo run deep:clean`,tags:[`root`]},{script:`rimraf node_modules dist .turbo`,tags:[`node`]}],"db:push":[{script:`drizzle-kit push`,tags:[`drizzle`,`db`]},{script:`turbo run db:push`,tags:[`db`,`root`]}],"db:studio":[{script:`drizzle-kit studio`,tags:[`drizzle`,`db`]},{script:`turbo run db:studio`,tags:[`db`,`root`]}],typecheck:[{script:`turbo run typecheck`,tags:[`node`,`root`]},{script:`tsc --noEmit`,tags:[`node`]}],format:[{script:`turbo run format`,tags:[`node`,`root`]},{script:`biome format --write .`,tags:[`node`,`biome`,`prettier`]},{script:`prettier --write .`,tags:[`node`,`prettier`]}],"format:check":[{script:`turbo run format:check`,tags:[`node`,`root`]},{script:`biome ci .`,tags:[`node`,`biome`,`prettier`]},{script:`prettier --check .`,tags:[`node`,`prettier`]}],test:[{script:`turbo run test`,tags:[`node`,`vitest`,`root`]},{script:`vitest run`,tags:[`node`,`vitest`]}]},G_={packageManager:`pnpm@10.28.2`,node:`>=22`};var K_=class{static objSorter(e,t=[]){let n=Object.fromEntries(Object.entries(e).filter(([,e])=>e!=null)),r=[];for(let e of t)e in n&&(r.push([e,n[e]]),delete n[e]);for(let e of Object.entries(n))r.push(e);return Object.fromEntries(r)}static handlePackageJson(e){let t=!!e.app.devDependencies?.turbo,n=t?[...e.tags,`root`]:[...e.tags],r=t?{version:`1.0.0`,packageManager:G_.packageManager,engines:{node:G_.node}}:{},i=Object.fromEntries(Object.entries(W_).map(([e,t])=>{let r=t.find(e=>e.tags.every(e=>n.includes(e)));return r?[e,r.script]:null}).filter(e=>e!==null)),a=e=>Object.fromEntries(Object.entries(e??{}).filter(([e])=>{let t=U_[e];return!t||t.tags.every(e=>n.includes(e))})),o=a(e.app.dependencies),s=a(e.app.devDependencies);for(let[e,t]of Object.entries(o))t.includes(`workspace:`)&&delete o[e];for(let[e,t]of Object.entries(s))t.includes(`workspace:`)&&delete s[e];if(e.dependencies)for(let[t,n]of Object.entries(e.dependencies))o[t]||(o[t]=n);e.app.startx?.requiredDevDeps?.forEach(e=>s[e]=`workspace:^`),e.app.startx?.requiredDeps?.forEach(e=>o[e]=`workspace:^`);for(let[e,r]of Object.entries(U_)){if(!r.tags.every(e=>n.includes(e))||t&&!r.tags.includes(`root`))continue;let i=r.isDevDependency;i&&!s[e]?s[e]=r.version:!i&&!o[e]&&(o[e]=r.version)}for(let t of e.app.startx?.ignore??[])delete o[t],delete s[t];let c={name:e.name||e.app.name,description:e.app.description,type:`module`,exports:e.app.exports,files:e.app.files,scripts:i,dependencies:o,devDependencies:s,...r};return{packageJson:this.objSorter(c,[`name`,`description`,`version`,`type`,`scripts`,`files`,`exports`,`dependencies`,`devDependencies`,`packageManager`,`engines`]),isWorkspace:t}}};const q_=(e,t=[])=>e.name===`up`||t.includes(`vim`)&&e.name===`k`||t.includes(`emacs`)&&e.ctrl&&e.name===`p`,J_=(e,t=[])=>e.name===`down`||t.includes(`vim`)&&e.name===`j`||t.includes(`emacs`)&&e.ctrl&&e.name===`n`,Y_=e=>e.name===`space`,X_=e=>e.name===`backspace`,Z_=e=>e.name===`tab`,Q_=e=>`1234567890`.includes(e.name),$_=e=>e.name===`enter`||e.name===`return`;var ev=class extends Error{name=`AbortPromptError`;message=`Prompt was aborted`;constructor(e){super(),this.cause=e?.cause}},tv=class extends Error{name=`CancelPromptError`;message=`Prompt was canceled`},nv=class extends Error{name=`ExitPromptError`},rv=class extends Error{name=`HookError`},iv=class extends Error{name=`ValidationError`};const av=new o;function ov(e){return{rl:e,hooks:[],hooksCleanup:[],hooksEffect:[],index:0,handleChange(){}}}function sv(e,t){let n=ov(e);return av.run(n,()=>{function e(e){n.handleChange=()=>{n.index=0,e()},n.handleChange()}return t(e)})}function cv(){let e=av.getStore();if(!e)throw new rv(`[Inquirer] Hook functions can only be called from within a prompt`);return e}function lv(){return cv().rl}function uv(e){return s.bind((...t)=>{let n=cv(),r=!1,i=n.handleChange;n.handleChange=()=>{r=!0};let a=e(...t);return r&&i(),n.handleChange=i,a})}function dv(e){let t=cv(),{index:n}=t,r=e({get(){return t.hooks[n]},set(e){t.hooks[n]=e},initialized:n in t.hooks});return t.index++,r}function fv(){cv().handleChange()}const pv={queue(e){let t=cv(),{index:n}=t;t.hooksEffect.push(()=>{t.hooksCleanup[n]?.();let r=e(lv());if(r!=null&&typeof r!=`function`)throw new iv(`useEffect return value must be a cleanup function or nothing.`);t.hooksCleanup[n]=r})},run(){let e=cv();uv(()=>{e.hooksEffect.forEach(e=>{e()}),e.hooksEffect.length=0})()},clearAll(){let e=cv();e.hooksCleanup.forEach(e=>{e?.()}),e.hooksEffect.length=0,e.hooksCleanup.length=0}};function Q(e){return dv(t=>{let n=s.bind(function(e){t.get()!==e&&(t.set(e),fv())});if(t.initialized)return[t.get(),n];let r=typeof e==`function`?e():e;return t.set(r),[r,n]})}function mv(e,t){dv(n=>{let r=n.get();(!Array.isArray(r)||t.some((e,t)=>!Object.is(e,r[t])))&&pv.queue(e),n.set(t)})}function hv(){return i.platform===`win32`?!!i.env.WT_SESSION||!!i.env.TERMINUS_SUBLIME||i.env.ConEmuTask===`{cmd::Cmder}`||i.env.TERM_PROGRAM===`Terminus-Sublime`||i.env.TERM_PROGRAM===`vscode`||i.env.TERM===`xterm-256color`||i.env.TERM===`alacritty`||i.env.TERMINAL_EMULATOR===`JetBrains-JediTerm`:i.env.TERM!==`linux`}const gv={circleQuestionMark:`(?)`,questionMarkPrefix:`(?)`,square:`█`,squareDarkShade:`▓`,squareMediumShade:`▒`,squareLightShade:`░`,squareTop:`▀`,squareBottom:`▄`,squareLeft:`▌`,squareRight:`▐`,squareCenter:`■`,bullet:`●`,dot:`․`,ellipsis:`…`,pointerSmall:`›`,triangleUp:`▲`,triangleUpSmall:`▴`,triangleDown:`▼`,triangleDownSmall:`▾`,triangleLeftSmall:`◂`,triangleRightSmall:`▸`,home:`⌂`,heart:`♥`,musicNote:`♪`,musicNoteBeamed:`♫`,arrowUp:`↑`,arrowDown:`↓`,arrowLeft:`←`,arrowRight:`→`,arrowLeftRight:`↔`,arrowUpDown:`↕`,almostEqual:`≈`,notEqual:`≠`,lessOrEqual:`≤`,greaterOrEqual:`≥`,identical:`≡`,infinity:`∞`,subscriptZero:`₀`,subscriptOne:`₁`,subscriptTwo:`₂`,subscriptThree:`₃`,subscriptFour:`₄`,subscriptFive:`₅`,subscriptSix:`₆`,subscriptSeven:`₇`,subscriptEight:`₈`,subscriptNine:`₉`,oneHalf:`½`,oneThird:`⅓`,oneQuarter:`¼`,oneFifth:`⅕`,oneSixth:`⅙`,oneEighth:`⅛`,twoThirds:`⅔`,twoFifths:`⅖`,threeQuarters:`¾`,threeFifths:`⅗`,threeEighths:`⅜`,fourFifths:`⅘`,fiveSixths:`⅚`,fiveEighths:`⅝`,sevenEighths:`⅞`,line:`─`,lineBold:`━`,lineDouble:`═`,lineDashed0:`┄`,lineDashed1:`┅`,lineDashed2:`┈`,lineDashed3:`┉`,lineDashed4:`╌`,lineDashed5:`╍`,lineDashed6:`╴`,lineDashed7:`╶`,lineDashed8:`╸`,lineDashed9:`╺`,lineDashed10:`╼`,lineDashed11:`╾`,lineDashed12:`−`,lineDashed13:`–`,lineDashed14:`‐`,lineDashed15:`⁃`,lineVertical:`│`,lineVerticalBold:`┃`,lineVerticalDouble:`║`,lineVerticalDashed0:`┆`,lineVerticalDashed1:`┇`,lineVerticalDashed2:`┊`,lineVerticalDashed3:`┋`,lineVerticalDashed4:`╎`,lineVerticalDashed5:`╏`,lineVerticalDashed6:`╵`,lineVerticalDashed7:`╷`,lineVerticalDashed8:`╹`,lineVerticalDashed9:`╻`,lineVerticalDashed10:`╽`,lineVerticalDashed11:`╿`,lineDownLeft:`┐`,lineDownLeftArc:`╮`,lineDownBoldLeftBold:`┓`,lineDownBoldLeft:`┒`,lineDownLeftBold:`┑`,lineDownDoubleLeftDouble:`╗`,lineDownDoubleLeft:`╖`,lineDownLeftDouble:`╕`,lineDownRight:`┌`,lineDownRightArc:`╭`,lineDownBoldRightBold:`┏`,lineDownBoldRight:`┎`,lineDownRightBold:`┍`,lineDownDoubleRightDouble:`╔`,lineDownDoubleRight:`╓`,lineDownRightDouble:`╒`,lineUpLeft:`┘`,lineUpLeftArc:`╯`,lineUpBoldLeftBold:`┛`,lineUpBoldLeft:`┚`,lineUpLeftBold:`┙`,lineUpDoubleLeftDouble:`╝`,lineUpDoubleLeft:`╜`,lineUpLeftDouble:`╛`,lineUpRight:`└`,lineUpRightArc:`╰`,lineUpBoldRightBold:`┗`,lineUpBoldRight:`┖`,lineUpRightBold:`┕`,lineUpDoubleRightDouble:`╚`,lineUpDoubleRight:`╙`,lineUpRightDouble:`╘`,lineUpDownLeft:`┤`,lineUpBoldDownBoldLeftBold:`┫`,lineUpBoldDownBoldLeft:`┨`,lineUpDownLeftBold:`┥`,lineUpBoldDownLeftBold:`┩`,lineUpDownBoldLeftBold:`┪`,lineUpDownBoldLeft:`┧`,lineUpBoldDownLeft:`┦`,lineUpDoubleDownDoubleLeftDouble:`╣`,lineUpDoubleDownDoubleLeft:`╢`,lineUpDownLeftDouble:`╡`,lineUpDownRight:`├`,lineUpBoldDownBoldRightBold:`┣`,lineUpBoldDownBoldRight:`┠`,lineUpDownRightBold:`┝`,lineUpBoldDownRightBold:`┡`,lineUpDownBoldRightBold:`┢`,lineUpDownBoldRight:`┟`,lineUpBoldDownRight:`┞`,lineUpDoubleDownDoubleRightDouble:`╠`,lineUpDoubleDownDoubleRight:`╟`,lineUpDownRightDouble:`╞`,lineDownLeftRight:`┬`,lineDownBoldLeftBoldRightBold:`┳`,lineDownLeftBoldRightBold:`┯`,lineDownBoldLeftRight:`┰`,lineDownBoldLeftBoldRight:`┱`,lineDownBoldLeftRightBold:`┲`,lineDownLeftRightBold:`┮`,lineDownLeftBoldRight:`┭`,lineDownDoubleLeftDoubleRightDouble:`╦`,lineDownDoubleLeftRight:`╥`,lineDownLeftDoubleRightDouble:`╤`,lineUpLeftRight:`┴`,lineUpBoldLeftBoldRightBold:`┻`,lineUpLeftBoldRightBold:`┷`,lineUpBoldLeftRight:`┸`,lineUpBoldLeftBoldRight:`┹`,lineUpBoldLeftRightBold:`┺`,lineUpLeftRightBold:`┶`,lineUpLeftBoldRight:`┵`,lineUpDoubleLeftDoubleRightDouble:`╩`,lineUpDoubleLeftRight:`╨`,lineUpLeftDoubleRightDouble:`╧`,lineUpDownLeftRight:`┼`,lineUpBoldDownBoldLeftBoldRightBold:`╋`,lineUpDownBoldLeftBoldRightBold:`╈`,lineUpBoldDownLeftBoldRightBold:`╇`,lineUpBoldDownBoldLeftRightBold:`╊`,lineUpBoldDownBoldLeftBoldRight:`╉`,lineUpBoldDownLeftRight:`╀`,lineUpDownBoldLeftRight:`╁`,lineUpDownLeftBoldRight:`┽`,lineUpDownLeftRightBold:`┾`,lineUpBoldDownBoldLeftRight:`╂`,lineUpDownLeftBoldRightBold:`┿`,lineUpBoldDownLeftBoldRight:`╃`,lineUpBoldDownLeftRightBold:`╄`,lineUpDownBoldLeftBoldRight:`╅`,lineUpDownBoldLeftRightBold:`╆`,lineUpDoubleDownDoubleLeftDoubleRightDouble:`╬`,lineUpDoubleDownDoubleLeftRight:`╫`,lineUpDownLeftDoubleRightDouble:`╪`,lineCross:`╳`,lineBackslash:`╲`,lineSlash:`╱`},_v={tick:`✔`,info:`ℹ`,warning:`⚠`,cross:`✘`,squareSmall:`◻`,squareSmallFilled:`◼`,circle:`◯`,circleFilled:`◉`,circleDotted:`◌`,circleDouble:`◎`,circleCircle:`ⓞ`,circleCross:`ⓧ`,circlePipe:`Ⓘ`,radioOn:`◉`,radioOff:`◯`,checkboxOn:`☒`,checkboxOff:`☐`,checkboxCircleOn:`ⓧ`,checkboxCircleOff:`Ⓘ`,pointer:`❯`,triangleUpOutline:`△`,triangleLeft:`◀`,triangleRight:`▶`,lozenge:`◆`,lozengeOutline:`◇`,hamburger:`☰`,smiley:`㋡`,mustache:`෴`,star:`★`,play:`▶`,nodejs:`⬢`,oneSeventh:`⅐`,oneNinth:`⅑`,oneTenth:`⅒`},vv={tick:`√`,info:`i`,warning:`‼`,cross:`×`,squareSmall:`□`,squareSmallFilled:`■`,circle:`( )`,circleFilled:`(*)`,circleDotted:`( )`,circleDouble:`( )`,circleCircle:`(○)`,circleCross:`(×)`,circlePipe:`(│)`,radioOn:`(*)`,radioOff:`( )`,checkboxOn:`[×]`,checkboxOff:`[ ]`,checkboxCircleOn:`(×)`,checkboxCircleOff:`( )`,pointer:`>`,triangleUpOutline:`∆`,triangleLeft:`◄`,triangleRight:`►`,lozenge:`♦`,lozengeOutline:`◊`,hamburger:`≡`,smiley:`☺`,mustache:`┌─┐`,star:`✶`,play:`►`,nodejs:`♦`,oneSeventh:`1/7`,oneNinth:`1/9`,oneTenth:`1/10`},yv={...gv,..._v},bv={...gv,...vv};var xv=hv()?yv:bv;Object.entries(_v);const Sv={prefix:{idle:l(`blue`,`?`),done:l(`green`,xv.tick)},spinner:{interval:80,frames:[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`].map(e=>l(`yellow`,e))},style:{answer:e=>l(`cyan`,e),message:e=>l(`bold`,e),error:e=>l(`red`,`> ${e}`),defaultAnswer:e=>l(`dim`,`(${e})`),help:e=>l(`dim`,e),highlight:e=>l(`cyan`,e),key:e=>l(`cyan`,l(`bold`,`<${e}>`))}};function Cv(e){if(typeof e!=`object`||!e)return!1;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function wv(...e){let t={};for(let n of e)for(let[e,r]of Object.entries(n)){let n=t[e];t[e]=Cv(n)&&Cv(r)?wv(n,r):r}return t}function Tv(...e){return wv(Sv,...e.filter(e=>e!=null))}function Ev({status:e=`idle`,theme:t}){let[n,r]=Q(!1),[i,a]=Q(0),{prefix:o,spinner:s}=Tv(t);return mv(()=>{if(e===`loading`){let e,t=-1,n=setTimeout(()=>{r(!0),e=setInterval(()=>{t+=1,a(t%s.frames.length)},s.interval)},300);return()=>{clearTimeout(n),clearInterval(e)}}else r(!1)},[e]),n?s.frames[i]:typeof o==`string`?o:o[e===`loading`?`idle`:e]??o.idle}function Dv(e,t){return dv(n=>{let r=n.get();if(!r||r.dependencies.length!==t.length||r.dependencies.some((e,n)=>e!==t[n])){let r=e();return n.set({value:r,dependencies:t}),r}return r.value})}function Ov(e){return Q({current:e})[0]}function kv(e){let t=Ov(e);t.current=e,mv(e=>{let n=!1,r=uv((r,i)=>{n||t.current(i,e)});return e.input.on(`keypress`,r),()=>{n=!0,e.input.removeListener(`keypress`,r)}},[])}var Av=_(((e,t)=>{t.exports=r;function n(e){let t={defaultWidth:0,output:process.stdout,tty:x(`tty`)};return e?(Object.keys(t).forEach(function(n){e[n]||(e[n]=t[n])}),e):t}function r(e){let t=n(e);if(t.output.getWindowSize)return t.output.getWindowSize()[0]||t.defaultWidth;if(t.tty.getWindowSize)return t.tty.getWindowSize()[1]||t.defaultWidth;if(t.output.columns)return t.output.columns;if(process.env.CLI_WIDTH){let e=parseInt(process.env.CLI_WIDTH,10);if(!isNaN(e)&&e!==0)return e}return t.defaultWidth}}));const jv=(()=>{let e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let n=0;for(e.lastIndex=0;e.test(t);)n+=1;return t.length-n}})(),Mv=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,Nv=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141,Pv=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,Fv=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,Iv=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy,Lv=/\t{1,1000}/y,Rv=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy,zv=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,Bv=/\p{M}+/gu,Vv={limit:1/0,ellipsis:``},Hv=(e,t={},n={})=>{let r=t.limit??1/0,i=t.ellipsis??``,a=t?.ellipsisWidth??(i?Hv(i,Vv,n).width:0),o=n.controlWidth??0,s=n.tabWidth??8,c=n.emojiWidth??2,l=n.regularWidth??1,u=n.wideWidth??2,d=[[zv,l],[Pv,0],[Fv,o],[Lv,s],[Rv,c],[Iv,u]],f=0,p=0,m=e.length,h=0,g=!1,_=m,v=Math.max(0,r-a),y=0,b=0,x=0,S=0;outer:for(;;){if(b>y||p>=m&&p>f){let t=e.slice(y,b)||e.slice(f,p);h=0;for(let e of t.replaceAll(Bv,``)){let t=e.codePointAt(0)||0;if(S=Mv(t)?2:Nv(t)?u:l,x+S>v&&(_=Math.min(_,Math.max(y,f)+h)),x+S>r){g=!0;break outer}h+=e.length,x+=S}y=b=0}if(p>=m)break outer;for(let t=0,n=d.length;t<n;t++){let[n,i]=d[t];if(n.lastIndex=p,n.test(e)){if(h=n===Iv?jv(e.slice(p,n.lastIndex)):n===Rv?1:n.lastIndex-p,S=h*i,x+S>v&&(_=Math.min(_,p+Math.floor((v-x)/i))),x+S>r){g=!0;break outer}x+=S,y=f,b=p,p=f=n.lastIndex;continue outer}}p+=1}return{width:g?v:x,index:g?_:m,truncated:g,ellipsed:g&&r>=a}};var Uv=Hv;const Wv={limit:1/0,ellipsis:``,ellipsisWidth:0};var Gv=(e,t={})=>Uv(e,Wv,t).width;const Kv=`]8;;`,qv=RegExp(`(?:\\[(?<code>\\d+)m|\\${Kv}(?<uri>.*))`,`y`),Jv=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},Yv=e=>`[${e}m`,Xv=e=>`${Kv}${e}`,Zv=(e,t,n)=>{let r=t[Symbol.iterator](),i=!1,a=!1,o=e.at(-1),s=o===void 0?0:Gv(o),c=r.next(),l=r.next(),u=0;for(;!c.done;){let o=c.value,d=Gv(o);s+d<=n?e[e.length-1]+=o:(e.push(o),s=0),(o===`\x1B`||o===``)&&(i=!0,a=t.startsWith(Kv,u+1)),i?a?o===`\x07`&&(i=!1,a=!1):o===`m`&&(i=!1):(s+=d,s===n&&!l.done&&(e.push(``),s=0)),c=l,l=r.next(),u+=o.length}o=e.at(-1),!s&&o!==void 0&&o.length&&e.length>1&&(e[e.length-2]+=e.pop())},Qv=e=>{let t=e.split(` `),n=t.length;for(;n&&!Gv(t[n-1]);)n--;return n===t.length?e:t.slice(0,n).join(` `)+t.slice(n).join(``)},$v=(e,t,n={})=>{if(n.trim!==!1&&e.trim()===``)return``;let r=``,i,a,o=e.split(` `),s=[``],c=0;for(let e=0;e<o.length;e++){let r=o[e];if(n.trim!==!1){let e=s.at(-1)??``,t=e.trimStart();e.length!==t.length&&(s[s.length-1]=t,c=Gv(t))}e!==0&&(c>=t&&(n.wordWrap===!1||n.trim===!1)&&(s.push(``),c=0),(c||n.trim===!1)&&(s[s.length-1]+=` `,c++));let i=Gv(r);if(n.hard&&i>t){let e=t-c,n=1+Math.floor((i-e-1)/t);Math.floor((i-1)/t)<n&&s.push(``),Zv(s,r,t),c=Gv(s.at(-1)??``);continue}if(c+i>t&&c&&i){if(n.wordWrap===!1&&c<t){Zv(s,r,t),c=Gv(s.at(-1)??``);continue}s.push(``),c=0}if(c+i>t&&n.wordWrap===!1){Zv(s,r,t),c=Gv(s.at(-1)??``);continue}s[s.length-1]+=r,c+=i}n.trim!==!1&&(s=s.map(e=>Qv(e)));let l=s.join(`
|
|
187
|
+
`,e)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case`alias`:case`scalar`:case`single-quoted-scalar`:case`double-quoted-scalar`:return this.flowScalar(this.type);case`block-scalar-header`:return{type:`block-scalar`,offset:this.offset,indent:this.indent,props:[this.sourceToken],source:``};case`flow-map-start`:case`flow-seq-start`:return{type:`flow-collection`,offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case`seq-item-ind`:return{type:`block-seq`,offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case`explicit-key-ind`:{this.onKeyLine=!0;let t=c(s(e));return t.push(this.sourceToken),{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,explicitKey:!0}]}}case`map-value-ind`:{this.onKeyLine=!0;let t=c(s(e));return{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,t){return this.type!==`comment`||this.indent<=t?!1:e.every(e=>e.type===`newline`||e.type===`space`)}*documentEnd(e){this.type!==`doc-mode`&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case`comma`:case`doc-start`:case`doc-end`:case`flow-seq-end`:case`flow-map-end`:case`map-value-ind`:yield*this.pop(),yield*this.step();break;case`newline`:this.onKeyLine=!1;default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop())}}}})),I_=_((e=>{var t=O_(),n=d_(),r=f_(),i=Ig(),a=X(),o=P_(),s=F_();function c(e){let t=e.prettyErrors!==!1;return{lineCounter:e.lineCounter||t&&new o.LineCounter||null,prettyErrors:t}}function l(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=Array.from(l.compose(o.parse(e)));if(a&&i)for(let t of u)t.errors.forEach(r.prettifyError(e,i)),t.warnings.forEach(r.prettifyError(e,i));return u.length>0?u:Object.assign([],{empty:!0},l.streamInfo())}function u(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=null;for(let t of l.compose(o.parse(e),!0,e.length))if(!u)u=t;else if(u.options.logLevel!==`silent`){u.errors.push(new r.YAMLParseError(t.range.slice(0,2),`MULTIPLE_DOCS`,`Source contains multiple documents; please use YAML.parseAllDocuments()`));break}return a&&i&&(u.errors.forEach(r.prettifyError(e,i)),u.warnings.forEach(r.prettifyError(e,i))),u}function d(e,t,n){let r;typeof t==`function`?r=t:n===void 0&&t&&typeof t==`object`&&(n=t);let a=u(e,n);if(!a)return null;if(a.warnings.forEach(e=>i.warn(a.options.logLevel,e)),a.errors.length>0){if(a.options.logLevel!==`silent`)throw a.errors[0];a.errors=[]}return a.toJS(Object.assign({reviver:r},n))}function f(e,t,r){let i=null;if(typeof t==`function`||Array.isArray(t)?i=t:r===void 0&&t&&(r=t),typeof r==`string`&&(r=r.length),typeof r==`number`){let e=Math.round(r);r=e<1?void 0:e>8?{indent:8}:{indent:e}}if(e===void 0){let{keepUndefined:e}=r??t??{};if(!e)return}return a.isDocument(e)&&!i?e.toString(r):new n.Document(e,i,r).toString(r)}e.parse=d,e.parseAllDocuments=l,e.parseDocument=u,e.stringify=f})),L_=b(_((e=>{var t=O_(),n=d_(),r=l_(),i=f_(),a=Og(),o=X(),s=zg(),c=Z(),l=Vg(),u=Ug();M_();var d=N_(),f=P_(),p=F_(),m=I_(),h=Sg();e.Composer=t.Composer,e.Document=n.Document,e.Schema=r.Schema,e.YAMLError=i.YAMLError,e.YAMLParseError=i.YAMLParseError,e.YAMLWarning=i.YAMLWarning,e.Alias=a.Alias,e.isAlias=o.isAlias,e.isCollection=o.isCollection,e.isDocument=o.isDocument,e.isMap=o.isMap,e.isNode=o.isNode,e.isPair=o.isPair,e.isScalar=o.isScalar,e.isSeq=o.isSeq,e.Pair=s.Pair,e.Scalar=c.Scalar,e.YAMLMap=l.YAMLMap,e.YAMLSeq=u.YAMLSeq,e.Lexer=d.Lexer,e.LineCounter=f.LineCounter,e.Parser=p.Parser,e.parse=m.parse,e.parseAllDocuments=m.parseAllDocuments,e.parseDocument=m.parseDocument,e.stringify=m.stringify,e.visit=h.visit,e.visitAsync=h.visitAsync}))(),1);function R_(){return nm.NODE_ENV===`development`?t.resolve(process.cwd(),`../../`):process.cwd()}const z_=new class{root=R_();async pathExists(e){try{return await a.access(e),!0}catch{return!1}}async writeFile({file:e,content:n}){await a.writeFile(t.resolve(this.root,e),n)}async writeJSONFile({file:e,content:n,dir:r}){e=`${e}.json`;let i=t.resolve(this.root,e);if(r){let n=t.resolve(this.root,r);await this.ensurePathExists({dir:r}),i=t.resolve(n,e)}await a.writeFile(i,JSON.stringify(n,null,2))}async readFile({file:e}){return await a.readFile(t.resolve(this.root,e),`utf-8`)}async readJSONFile({file:e,dir:n}){try{e=`${e}.json`;let r=t.resolve(this.root,n??``,e),i=await a.readFile(r,`utf-8`);return JSON.parse(i)}catch(t){return console.error(`Failed to read JSON file at ${e}:`,t),null}}async readYamlFile({file:e,dir:n}){try{e=`${e}.yaml`;let r=t.resolve(this.root,n??``,e),i=await a.readFile(r,`utf-8`);return L_.parseDocument(i)}catch(t){return console.error(`Failed to read Yaml file at ${e}:`,t),null}}async ensurePathExists({dir:e}){let n=t.resolve(this.root,e);await this.pathExists(n)||await a.mkdir(n,{recursive:!0})}async avoidOverriding({file:e}){let n=t.resolve(this.root,e);if(await this.pathExists(n))throw Error(`File ${n} already exists`)}async removeFile({file:e}){let n=t.resolve(this.root,e);await this.pathExists(n)&&await a.unlink(n)}async removeDirectory({dir:e,target:n}){let r=t.resolve(this.root,e,n);await this.pathExists(r)&&await a.rm(r,{recursive:!0,force:!0})}async copyFile({from:e,to:n}){await this.ensurePathExists({dir:t.dirname(n)}),await a.copyFile(t.resolve(this.root,e),t.resolve(this.root,n))}async copyDirectory({from:e,to:n,recursive:r=!0,include:i,exclude:o}){let s=t.resolve(this.root,e),c=t.resolve(this.root,n);if(!await this.pathExists(s))return;await this.ensurePathExists({dir:t.join(n)});let l=await a.readdir(s,{withFileTypes:!0});for(let u of l){let l=t.join(s,u.name),d=t.join(c,u.name),f=(!i||i.test(u.name))&&(!o||!o.test(u.name));u.isDirectory()?r&&await this.copyDirectory({from:t.join(e,u.name),to:t.join(n,u.name),recursive:r,include:i,exclude:o}):u.isFile()&&f&&await a.copyFile(l,d)}}async listDirectories({dir:e}){try{return(await a.readdir(t.resolve(this.root,e),{withFileTypes:!0})).filter(e=>e.isDirectory()).map(e=>e.name)}catch(t){return console.error(`Error listing directories in ${e}:`,t),[]}}async listFiles({dir:e}){try{return(await a.readdir(t.resolve(this.root,e),{withFileTypes:!0})).filter(e=>e.isFile()).map(e=>e.name)}catch(t){return console.error(`Error listing files in ${e}:`,t),[]}}},B_={"startx.json":{tags:[`never`]},".npmignore":{tags:[`never`]},".npmrc":{tags:[`never`]},".prettier.cjs":{tags:[`prettier`]},".prettierignore":{tags:[`biome`]},"biome.json":{tags:[`biome`]},"pnpm-lock.yaml":{tags:[`never`]},"pnpm-workspace.yaml":{tags:[`root`]},"turbo.json":{tags:[`root`]},LICENSE:{tags:[`never`]},".env":{tags:[`never`]},"tsdown.config.ts":{tags:[`tsdown`]},"eslint.config.ts":{tags:[`eslint`,`node`]},"vitest.config.ts":{tags:[`vitest`,`node`]},"package.json":{tags:[`never`]}},V_=tm({STARTX_ENV:Gp.enum([`development`,`production`,`test`,`staging`]).default(`production`)});var H_=class{static getDirectory(){let e=n(import.meta.url),r=t.dirname(e),i=process.cwd();return r=V_.STARTX_ENV===`development`?t.resolve(r,`../../../../`):t.resolve(r,`../../../`),{template:r,workspace:i}}static async getPackageList(){let e=this.getDirectory().template,n=async(n,r,i=``,a)=>{let o=t.join(e,...n.split(`/`));try{let n=await z_.listDirectories({dir:o});return a&&(n=n.filter(a)),(await Promise.all(n.map(async n=>{let a=t.join(o,n),s=t.relative(e,a),c=i?`${i}${n}`:n,l;try{l=await this.parsePackageJson({dir:a})}catch{l=null}return l?{type:r,path:a,relativePath:s,name:c,packageJson:l}:(console.error(`Ignoring this package failed to read package.json: ${c}`),null)}))).filter(e=>e!==null)}catch(e){return console.error(`Error reading directory ${o}:`,e),[]}},r=[`@repo`,`@db`];return(await Promise.all([n(`apps`,`apps`),n(`configs`,`configs`),n(`packages`,`packages`,``,e=>!r.includes(e)),n(`packages/@repo`,`packages`,`@repo/`),n(`packages/@db`,`packages`,`@db/`)])).flat()}static async parsePackageJson({dir:e,file:t=`package`}){return await z_.readJSONFile({dir:e,file:t})}static async parsePnpmWorkspace({dir:e}){return(await z_.readYamlFile({file:`pnpm-workspace`,dir:e}))?.toJSON()}};const U_={"@biomejs/biome":{tags:[`node`,`biome`,`root`],version:`catalog:`,isDevDependency:!0},prettier:{tags:[`node`,`prettier`,`root`],version:`catalog:`,isDevDependency:!0},eslint:{tags:[`node`,`eslint`,`root`],version:`catalog:`,isDevDependency:!0},vitest:{tags:[`node`,`vitest`,`root`],version:`catalog:`,isDevDependency:!0},tsdown:{isDevDependency:!0,tags:[`node`,`tsdown`,`root`],version:`catalog:`},"tsdown-config":{tags:[`node`,`tsdown`,`runnable`],version:`workspace:^`,isDevDependency:!0},"@types/node":{tags:[`node`,`root`],version:`catalog:`,isDevDependency:!0},"typescript-config":{tags:[`node`],version:`workspace:^`,isDevDependency:!0},"eslint-config":{tags:[`node`,`eslint`],version:`workspace:^`,isDevDependency:!0},"vitest-config":{tags:[`node`,`vitest`],version:`workspace:^`,isDevDependency:!0}},W_={dev:[{script:`turbo run dev`,tags:[`runnable`,`root`]},{script:`tsx watch src/index.ts`,tags:[`runnable`,`node`,`backend`,`express`]},{script:`email dev --port 3014 --dir ./src`,tags:[`node`,`mail`]}],"dev:debug":[{script:`turbo run dev:debug`,tags:[`node`,`runnable`,`root`]},{script:`tsx watch --inspect src/index.ts`,tags:[`backend`,`node`,`runnable`,`express`]}],"bun:dev":[{script:`turbo run bun:dev`,tags:[`node`,`runnable`,`root`]},{script:`bun --watch src/index.ts`,tags:[`backend`,`node`,`runnable`,`express`]}],build:[{script:`turbo run build`,tags:[`runnable`,`root`]},{script:`tsdown --config-loader unrun`,tags:[`runnable`,`node`,`tsdown`]}],cli:[{script:`turbo run cli -- `,tags:[`runnable`,`node`,`cli`,`root`]},{script:`tsx src/index.ts`,tags:[`runnable`,`node`,`cli`,`commander`]}],start:[{script:`turbo run start`,tags:[`backend`,`runnable`,`node`,`root`]},{script:`node dist/index.mjs`,tags:[`node`,`runnable`]}],lint:[{script:`turbo run lint`,tags:[`node`,`eslint`,`root`]},{script:`eslint .`,tags:[`node`,`eslint`]}],"lint:fix":[{script:`turbo run lint:fix`,tags:[`node`,`eslint`,`root`]},{script:`eslint . src/**/*.ts --fix`,tags:[`node`,`eslint`]}],clean:[{script:`turbo run clean`,tags:[`root`]},{script:`rimraf dist .turbo dist`,tags:[]}],"deep:clean":[{script:`turbo run deep:clean`,tags:[`root`]},{script:`rimraf node_modules dist .turbo`,tags:[`node`]}],"db:push":[{script:`drizzle-kit push`,tags:[`drizzle`,`db`]},{script:`turbo run db:push`,tags:[`db`,`root`]}],"db:studio":[{script:`drizzle-kit studio`,tags:[`drizzle`,`db`]},{script:`turbo run db:studio`,tags:[`db`,`root`]}],typecheck:[{script:`turbo run typecheck`,tags:[`node`,`root`]},{script:`tsc --noEmit`,tags:[`node`]}],format:[{script:`turbo run format`,tags:[`node`,`root`]},{script:`biome format --write .`,tags:[`node`,`biome`,`prettier`]},{script:`prettier --write .`,tags:[`node`,`prettier`]}],"format:check":[{script:`turbo run format:check`,tags:[`node`,`root`]},{script:`biome ci .`,tags:[`node`,`biome`,`prettier`]},{script:`prettier --check .`,tags:[`node`,`prettier`]}],test:[{script:`turbo run test`,tags:[`node`,`vitest`,`root`]},{script:`vitest run`,tags:[`node`,`vitest`]}]},G_={packageManager:`pnpm@10.28.2`,node:`>=22`};var K_=class{static objSorter(e,t=[]){let n=Object.fromEntries(Object.entries(e).filter(([,e])=>e!=null)),r=[];for(let e of t)e in n&&(r.push([e,n[e]]),delete n[e]);for(let e of Object.entries(n))r.push(e);return Object.fromEntries(r)}static handlePackageJson(e){let t=!!e.app.devDependencies?.turbo,n=t?[...e.tags,`root`]:[...e.tags],r=t?{version:`1.0.0`,packageManager:G_.packageManager,engines:{node:G_.node}}:{},i=Object.fromEntries(Object.entries(W_).map(([e,t])=>{let r=t.find(e=>e.tags.every(e=>n.includes(e)));return r?[e,r.script]:null}).filter(e=>e!==null)),a=e=>Object.fromEntries(Object.entries(e??{}).filter(([e])=>{let t=U_[e];return!t||t.tags.every(e=>n.includes(e))})),o=a(e.app.dependencies),s=a(e.app.devDependencies);for(let[e,t]of Object.entries(o))t.includes(`workspace:`)&&delete o[e];for(let[e,t]of Object.entries(s))t.includes(`workspace:`)&&delete s[e];if(e.dependencies)for(let[t,n]of Object.entries(e.dependencies))o[t]||(o[t]=n);e.app.startx?.requiredDevDeps?.forEach(e=>s[e]=`workspace:^`),e.app.startx?.requiredDeps?.forEach(e=>o[e]=`workspace:^`);for(let[e,r]of Object.entries(U_)){if(!r.tags.every(e=>n.includes(e))||t&&!r.tags.includes(`root`))continue;let i=r.isDevDependency;i&&!s[e]?s[e]=r.version:!i&&!o[e]&&(o[e]=r.version)}for(let t of e.app.startx?.ignore??[])delete o[t],delete s[t];let c={name:e.name||e.app.name,description:e.app.description,type:`module`,exports:e.app.exports,files:e.app.files,scripts:i,dependencies:o,devDependencies:s,...r};return{packageJson:this.objSorter(c,[`name`,`description`,`version`,`type`,`scripts`,`files`,`exports`,`dependencies`,`devDependencies`,`packageManager`,`engines`]),isWorkspace:t}}};const q_=(e,t=[])=>e.name===`up`||t.includes(`vim`)&&e.name===`k`||t.includes(`emacs`)&&e.ctrl&&e.name===`p`,J_=(e,t=[])=>e.name===`down`||t.includes(`vim`)&&e.name===`j`||t.includes(`emacs`)&&e.ctrl&&e.name===`n`,Y_=e=>e.name===`space`,X_=e=>e.name===`backspace`,Z_=e=>e.name===`tab`,Q_=e=>`1234567890`.includes(e.name),$_=e=>e.name===`enter`||e.name===`return`;var ev=class extends Error{name=`AbortPromptError`;message=`Prompt was aborted`;constructor(e){super(),this.cause=e?.cause}},tv=class extends Error{name=`CancelPromptError`;message=`Prompt was canceled`},nv=class extends Error{name=`ExitPromptError`},rv=class extends Error{name=`HookError`},iv=class extends Error{name=`ValidationError`};const av=new o;function ov(e){return{rl:e,hooks:[],hooksCleanup:[],hooksEffect:[],index:0,handleChange(){}}}function sv(e,t){let n=ov(e);return av.run(n,()=>{function e(e){n.handleChange=()=>{n.index=0,e()},n.handleChange()}return t(e)})}function cv(){let e=av.getStore();if(!e)throw new rv(`[Inquirer] Hook functions can only be called from within a prompt`);return e}function lv(){return cv().rl}function uv(e){return s.bind((...t)=>{let n=cv(),r=!1,i=n.handleChange;n.handleChange=()=>{r=!0};let a=e(...t);return r&&i(),n.handleChange=i,a})}function dv(e){let t=cv(),{index:n}=t,r=e({get(){return t.hooks[n]},set(e){t.hooks[n]=e},initialized:n in t.hooks});return t.index++,r}function fv(){cv().handleChange()}const pv={queue(e){let t=cv(),{index:n}=t;t.hooksEffect.push(()=>{t.hooksCleanup[n]?.();let r=e(lv());if(r!=null&&typeof r!=`function`)throw new iv(`useEffect return value must be a cleanup function or nothing.`);t.hooksCleanup[n]=r})},run(){let e=cv();uv(()=>{e.hooksEffect.forEach(e=>{e()}),e.hooksEffect.length=0})()},clearAll(){let e=cv();e.hooksCleanup.forEach(e=>{e?.()}),e.hooksEffect.length=0,e.hooksCleanup.length=0}};function Q(e){return dv(t=>{let n=s.bind(function(e){t.get()!==e&&(t.set(e),fv())});if(t.initialized)return[t.get(),n];let r=typeof e==`function`?e():e;return t.set(r),[r,n]})}function mv(e,t){dv(n=>{let r=n.get();(!Array.isArray(r)||t.some((e,t)=>!Object.is(e,r[t])))&&pv.queue(e),n.set(t)})}function hv(){return i.platform===`win32`?!!i.env.WT_SESSION||!!i.env.TERMINUS_SUBLIME||i.env.ConEmuTask===`{cmd::Cmder}`||i.env.TERM_PROGRAM===`Terminus-Sublime`||i.env.TERM_PROGRAM===`vscode`||i.env.TERM===`xterm-256color`||i.env.TERM===`alacritty`||i.env.TERMINAL_EMULATOR===`JetBrains-JediTerm`:i.env.TERM!==`linux`}const gv={circleQuestionMark:`(?)`,questionMarkPrefix:`(?)`,square:`█`,squareDarkShade:`▓`,squareMediumShade:`▒`,squareLightShade:`░`,squareTop:`▀`,squareBottom:`▄`,squareLeft:`▌`,squareRight:`▐`,squareCenter:`■`,bullet:`●`,dot:`․`,ellipsis:`…`,pointerSmall:`›`,triangleUp:`▲`,triangleUpSmall:`▴`,triangleDown:`▼`,triangleDownSmall:`▾`,triangleLeftSmall:`◂`,triangleRightSmall:`▸`,home:`⌂`,heart:`♥`,musicNote:`♪`,musicNoteBeamed:`♫`,arrowUp:`↑`,arrowDown:`↓`,arrowLeft:`←`,arrowRight:`→`,arrowLeftRight:`↔`,arrowUpDown:`↕`,almostEqual:`≈`,notEqual:`≠`,lessOrEqual:`≤`,greaterOrEqual:`≥`,identical:`≡`,infinity:`∞`,subscriptZero:`₀`,subscriptOne:`₁`,subscriptTwo:`₂`,subscriptThree:`₃`,subscriptFour:`₄`,subscriptFive:`₅`,subscriptSix:`₆`,subscriptSeven:`₇`,subscriptEight:`₈`,subscriptNine:`₉`,oneHalf:`½`,oneThird:`⅓`,oneQuarter:`¼`,oneFifth:`⅕`,oneSixth:`⅙`,oneEighth:`⅛`,twoThirds:`⅔`,twoFifths:`⅖`,threeQuarters:`¾`,threeFifths:`⅗`,threeEighths:`⅜`,fourFifths:`⅘`,fiveSixths:`⅚`,fiveEighths:`⅝`,sevenEighths:`⅞`,line:`─`,lineBold:`━`,lineDouble:`═`,lineDashed0:`┄`,lineDashed1:`┅`,lineDashed2:`┈`,lineDashed3:`┉`,lineDashed4:`╌`,lineDashed5:`╍`,lineDashed6:`╴`,lineDashed7:`╶`,lineDashed8:`╸`,lineDashed9:`╺`,lineDashed10:`╼`,lineDashed11:`╾`,lineDashed12:`−`,lineDashed13:`–`,lineDashed14:`‐`,lineDashed15:`⁃`,lineVertical:`│`,lineVerticalBold:`┃`,lineVerticalDouble:`║`,lineVerticalDashed0:`┆`,lineVerticalDashed1:`┇`,lineVerticalDashed2:`┊`,lineVerticalDashed3:`┋`,lineVerticalDashed4:`╎`,lineVerticalDashed5:`╏`,lineVerticalDashed6:`╵`,lineVerticalDashed7:`╷`,lineVerticalDashed8:`╹`,lineVerticalDashed9:`╻`,lineVerticalDashed10:`╽`,lineVerticalDashed11:`╿`,lineDownLeft:`┐`,lineDownLeftArc:`╮`,lineDownBoldLeftBold:`┓`,lineDownBoldLeft:`┒`,lineDownLeftBold:`┑`,lineDownDoubleLeftDouble:`╗`,lineDownDoubleLeft:`╖`,lineDownLeftDouble:`╕`,lineDownRight:`┌`,lineDownRightArc:`╭`,lineDownBoldRightBold:`┏`,lineDownBoldRight:`┎`,lineDownRightBold:`┍`,lineDownDoubleRightDouble:`╔`,lineDownDoubleRight:`╓`,lineDownRightDouble:`╒`,lineUpLeft:`┘`,lineUpLeftArc:`╯`,lineUpBoldLeftBold:`┛`,lineUpBoldLeft:`┚`,lineUpLeftBold:`┙`,lineUpDoubleLeftDouble:`╝`,lineUpDoubleLeft:`╜`,lineUpLeftDouble:`╛`,lineUpRight:`└`,lineUpRightArc:`╰`,lineUpBoldRightBold:`┗`,lineUpBoldRight:`┖`,lineUpRightBold:`┕`,lineUpDoubleRightDouble:`╚`,lineUpDoubleRight:`╙`,lineUpRightDouble:`╘`,lineUpDownLeft:`┤`,lineUpBoldDownBoldLeftBold:`┫`,lineUpBoldDownBoldLeft:`┨`,lineUpDownLeftBold:`┥`,lineUpBoldDownLeftBold:`┩`,lineUpDownBoldLeftBold:`┪`,lineUpDownBoldLeft:`┧`,lineUpBoldDownLeft:`┦`,lineUpDoubleDownDoubleLeftDouble:`╣`,lineUpDoubleDownDoubleLeft:`╢`,lineUpDownLeftDouble:`╡`,lineUpDownRight:`├`,lineUpBoldDownBoldRightBold:`┣`,lineUpBoldDownBoldRight:`┠`,lineUpDownRightBold:`┝`,lineUpBoldDownRightBold:`┡`,lineUpDownBoldRightBold:`┢`,lineUpDownBoldRight:`┟`,lineUpBoldDownRight:`┞`,lineUpDoubleDownDoubleRightDouble:`╠`,lineUpDoubleDownDoubleRight:`╟`,lineUpDownRightDouble:`╞`,lineDownLeftRight:`┬`,lineDownBoldLeftBoldRightBold:`┳`,lineDownLeftBoldRightBold:`┯`,lineDownBoldLeftRight:`┰`,lineDownBoldLeftBoldRight:`┱`,lineDownBoldLeftRightBold:`┲`,lineDownLeftRightBold:`┮`,lineDownLeftBoldRight:`┭`,lineDownDoubleLeftDoubleRightDouble:`╦`,lineDownDoubleLeftRight:`╥`,lineDownLeftDoubleRightDouble:`╤`,lineUpLeftRight:`┴`,lineUpBoldLeftBoldRightBold:`┻`,lineUpLeftBoldRightBold:`┷`,lineUpBoldLeftRight:`┸`,lineUpBoldLeftBoldRight:`┹`,lineUpBoldLeftRightBold:`┺`,lineUpLeftRightBold:`┶`,lineUpLeftBoldRight:`┵`,lineUpDoubleLeftDoubleRightDouble:`╩`,lineUpDoubleLeftRight:`╨`,lineUpLeftDoubleRightDouble:`╧`,lineUpDownLeftRight:`┼`,lineUpBoldDownBoldLeftBoldRightBold:`╋`,lineUpDownBoldLeftBoldRightBold:`╈`,lineUpBoldDownLeftBoldRightBold:`╇`,lineUpBoldDownBoldLeftRightBold:`╊`,lineUpBoldDownBoldLeftBoldRight:`╉`,lineUpBoldDownLeftRight:`╀`,lineUpDownBoldLeftRight:`╁`,lineUpDownLeftBoldRight:`┽`,lineUpDownLeftRightBold:`┾`,lineUpBoldDownBoldLeftRight:`╂`,lineUpDownLeftBoldRightBold:`┿`,lineUpBoldDownLeftBoldRight:`╃`,lineUpBoldDownLeftRightBold:`╄`,lineUpDownBoldLeftBoldRight:`╅`,lineUpDownBoldLeftRightBold:`╆`,lineUpDoubleDownDoubleLeftDoubleRightDouble:`╬`,lineUpDoubleDownDoubleLeftRight:`╫`,lineUpDownLeftDoubleRightDouble:`╪`,lineCross:`╳`,lineBackslash:`╲`,lineSlash:`╱`},_v={tick:`✔`,info:`ℹ`,warning:`⚠`,cross:`✘`,squareSmall:`◻`,squareSmallFilled:`◼`,circle:`◯`,circleFilled:`◉`,circleDotted:`◌`,circleDouble:`◎`,circleCircle:`ⓞ`,circleCross:`ⓧ`,circlePipe:`Ⓘ`,radioOn:`◉`,radioOff:`◯`,checkboxOn:`☒`,checkboxOff:`☐`,checkboxCircleOn:`ⓧ`,checkboxCircleOff:`Ⓘ`,pointer:`❯`,triangleUpOutline:`△`,triangleLeft:`◀`,triangleRight:`▶`,lozenge:`◆`,lozengeOutline:`◇`,hamburger:`☰`,smiley:`㋡`,mustache:`෴`,star:`★`,play:`▶`,nodejs:`⬢`,oneSeventh:`⅐`,oneNinth:`⅑`,oneTenth:`⅒`},vv={tick:`√`,info:`i`,warning:`‼`,cross:`×`,squareSmall:`□`,squareSmallFilled:`■`,circle:`( )`,circleFilled:`(*)`,circleDotted:`( )`,circleDouble:`( )`,circleCircle:`(○)`,circleCross:`(×)`,circlePipe:`(│)`,radioOn:`(*)`,radioOff:`( )`,checkboxOn:`[×]`,checkboxOff:`[ ]`,checkboxCircleOn:`(×)`,checkboxCircleOff:`( )`,pointer:`>`,triangleUpOutline:`∆`,triangleLeft:`◄`,triangleRight:`►`,lozenge:`♦`,lozengeOutline:`◊`,hamburger:`≡`,smiley:`☺`,mustache:`┌─┐`,star:`✶`,play:`►`,nodejs:`♦`,oneSeventh:`1/7`,oneNinth:`1/9`,oneTenth:`1/10`},yv={...gv,..._v},bv={...gv,...vv};var xv=hv()?yv:bv;Object.entries(_v);const Sv={prefix:{idle:l(`blue`,`?`),done:l(`green`,xv.tick)},spinner:{interval:80,frames:[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`].map(e=>l(`yellow`,e))},style:{answer:e=>l(`cyan`,e),message:e=>l(`bold`,e),error:e=>l(`red`,`> ${e}`),defaultAnswer:e=>l(`dim`,`(${e})`),help:e=>l(`dim`,e),highlight:e=>l(`cyan`,e),key:e=>l(`cyan`,l(`bold`,`<${e}>`))}};function Cv(e){if(typeof e!=`object`||!e)return!1;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function wv(...e){let t={};for(let n of e)for(let[e,r]of Object.entries(n)){let n=t[e];t[e]=Cv(n)&&Cv(r)?wv(n,r):r}return t}function Tv(...e){return wv(Sv,...e.filter(e=>e!=null))}function Ev({status:e=`idle`,theme:t}){let[n,r]=Q(!1),[i,a]=Q(0),{prefix:o,spinner:s}=Tv(t);return mv(()=>{if(e===`loading`){let e,t=-1,n=setTimeout(()=>{r(!0),e=setInterval(()=>{t+=1,a(t%s.frames.length)},s.interval)},300);return()=>{clearTimeout(n),clearInterval(e)}}else r(!1)},[e]),n?s.frames[i]:typeof o==`string`?o:o[e===`loading`?`idle`:e]??o.idle}function Dv(e,t){return dv(n=>{let r=n.get();if(!r||r.dependencies.length!==t.length||r.dependencies.some((e,n)=>e!==t[n])){let r=e();return n.set({value:r,dependencies:t}),r}return r.value})}function Ov(e){return Q({current:e})[0]}function kv(e){let t=Ov(e);t.current=e,mv(e=>{let n=!1,r=uv((r,i)=>{n||t.current(i,e)});return e.input.on(`keypress`,r),()=>{n=!0,e.input.removeListener(`keypress`,r)}},[])}var Av=_(((e,t)=>{t.exports=r;function n(e){let t={defaultWidth:0,output:process.stdout,tty:x(`tty`)};return e?(Object.keys(t).forEach(function(n){e[n]||(e[n]=t[n])}),e):t}function r(e){let t=n(e);if(t.output.getWindowSize)return t.output.getWindowSize()[0]||t.defaultWidth;if(t.tty.getWindowSize)return t.tty.getWindowSize()[1]||t.defaultWidth;if(t.output.columns)return t.output.columns;if(process.env.CLI_WIDTH){let e=parseInt(process.env.CLI_WIDTH,10);if(!isNaN(e)&&e!==0)return e}return t.defaultWidth}}));const jv=(()=>{let e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let n=0;for(e.lastIndex=0;e.test(t);)n+=1;return t.length-n}})(),Mv=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,Nv=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141,Pv=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,Fv=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,Iv=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy,Lv=/\t{1,1000}/y,Rv=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy,zv=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,Bv=/\p{M}+/gu,Vv={limit:1/0,ellipsis:``},Hv=(e,t={},n={})=>{let r=t.limit??1/0,i=t.ellipsis??``,a=t?.ellipsisWidth??(i?Hv(i,Vv,n).width:0),o=n.controlWidth??0,s=n.tabWidth??8,c=n.emojiWidth??2,l=n.regularWidth??1,u=n.wideWidth??2,d=[[zv,l],[Pv,0],[Fv,o],[Lv,s],[Rv,c],[Iv,u]],f=0,p=0,m=e.length,h=0,g=!1,_=m,v=Math.max(0,r-a),y=0,b=0,x=0,S=0;outer:for(;;){if(b>y||p>=m&&p>f){let t=e.slice(y,b)||e.slice(f,p);h=0;for(let e of t.replaceAll(Bv,``)){let t=e.codePointAt(0)||0;if(S=Mv(t)?2:Nv(t)?u:l,x+S>v&&(_=Math.min(_,Math.max(y,f)+h)),x+S>r){g=!0;break outer}h+=e.length,x+=S}y=b=0}if(p>=m)break outer;for(let t=0,n=d.length;t<n;t++){let[n,i]=d[t];if(n.lastIndex=p,n.test(e)){if(h=n===Iv?jv(e.slice(p,n.lastIndex)):n===Rv?1:n.lastIndex-p,S=h*i,x+S>v&&(_=Math.min(_,p+Math.floor((v-x)/i))),x+S>r){g=!0;break outer}x+=S,y=f,b=p,p=f=n.lastIndex;continue outer}}p+=1}return{width:g?v:x,index:g?_:m,truncated:g,ellipsed:g&&r>=a}};var Uv=Hv;const Wv={limit:1/0,ellipsis:``,ellipsisWidth:0};var Gv=(e,t={})=>Uv(e,Wv,t).width;const Kv=`]8;;`,qv=RegExp(`(?:\\[(?<code>\\d+)m|\\${Kv}(?<uri>.*))`,`y`),Jv=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},Yv=e=>`[${e}m`,Xv=e=>`${Kv}${e}`,Zv=(e,t,n)=>{let r=t[Symbol.iterator](),i=!1,a=!1,o=e.at(-1),s=o===void 0?0:Gv(o),c=r.next(),l=r.next(),u=0;for(;!c.done;){let o=c.value,d=Gv(o);s+d<=n?e[e.length-1]+=o:(e.push(o),s=0),(o===`\x1B`||o===``)&&(i=!0,a=t.startsWith(Kv,u+1)),i?a?o===`\x07`&&(i=!1,a=!1):o===`m`&&(i=!1):(s+=d,s===n&&!l.done&&(e.push(``),s=0)),c=l,l=r.next(),u+=o.length}o=e.at(-1),!s&&o!==void 0&&o.length&&e.length>1&&(e[e.length-2]+=e.pop())},Qv=e=>{let t=e.split(` `),n=t.length;for(;n&&!Gv(t[n-1]);)n--;return n===t.length?e:t.slice(0,n).join(` `)+t.slice(n).join(``)},$v=(e,t,n={})=>{if(n.trim!==!1&&e.trim()===``)return``;let r=``,i,a,o=e.split(` `),s=[``],c=0;for(let e=0;e<o.length;e++){let r=o[e];if(n.trim!==!1){let e=s.at(-1)??``,t=e.trimStart();e.length!==t.length&&(s[s.length-1]=t,c=Gv(t))}e!==0&&(c>=t&&(n.wordWrap===!1||n.trim===!1)&&(s.push(``),c=0),(c||n.trim===!1)&&(s[s.length-1]+=` `,c++));let i=Gv(r);if(n.hard&&i>t){let e=t-c,n=1+Math.floor((i-e-1)/t);Math.floor((i-1)/t)<n&&s.push(``),Zv(s,r,t),c=Gv(s.at(-1)??``);continue}if(c+i>t&&c&&i){if(n.wordWrap===!1&&c<t){Zv(s,r,t),c=Gv(s.at(-1)??``);continue}s.push(``),c=0}if(c+i>t&&n.wordWrap===!1){Zv(s,r,t),c=Gv(s.at(-1)??``);continue}s[s.length-1]+=r,c+=i}n.trim!==!1&&(s=s.map(e=>Qv(e)));let l=s.join(`
|
|
188
188
|
`),u=!1;for(let e=0;e<l.length;e++){let t=l[e];if(r+=t,u)u=!1;else if(u=t>=`\ud800`&&t<=`\udbff`,u)continue;if(t===`\x1B`||t===``){qv.lastIndex=e+1;let t=qv.exec(l)?.groups;if(t?.code!==void 0){let e=Number.parseFloat(t.code);i=e===39?void 0:e}else t?.uri!==void 0&&(a=t.uri.length===0?void 0:t.uri)}if(l[e+1]===`
|
|
189
189
|
`){a&&(r+=Xv(``));let e=i?Jv(i):void 0;i&&e&&(r+=Yv(e))}else t===`
|
|
190
190
|
`&&(i&&Jv(i)&&(r+=Yv(i)),a&&(r+=Xv(a)))}return r},ey=/\r?\n/;function ty(e,t,n){return String(e).normalize().split(ey).map(e=>$v(e,t,n)).join(`
|
|
@@ -200,4 +200,4 @@ $&`).replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g,`$1$2`).replace(/\
|
|
|
200
200
|
`+t:``),o=Math.floor(n.length/i)-this.cursorPos.rows+(t?Oy(t):0);o>0&&(a+=Cy(o)),a+=Ty(this.cursorPos.cols),this.write(wy(this.extraLinesUnderPrompt)+Dy(this.height)+a),this.extraLinesUnderPrompt=o,this.height=Oy(a)}checkCursorPos(){let e=this.rl.getCursorPos();e.cols!==this.cursorPos.cols&&(this.write(Ty(e.cols)),this.cursorPos=e)}done({clearContent:e}){this.rl.setPrompt(``);let t=wy(this.extraLinesUnderPrompt);t+=e?Dy(this.height):`
|
|
201
201
|
`,t+=`\x1B[?25h`,this.write(t),this.rl.close()}},jy=class extends Promise{static withResolver(){let e,t;return{promise:new Promise((n,r)=>{e=n,t=r}),resolve:e,reject:t}}},My=b(sy(),1);const Ny=globalThis.setImmediate;function Py(){let e=Error.prepareStackTrace,t=[];try{Error.prepareStackTrace=(e,n)=>{let r=n.slice(1);return t=r,r},Error().stack}catch{return t}return Error.prepareStackTrace=e,t}function Fy(e){let t=Py();return(n,r={})=>{let{input:i=process.stdin,signal:a}=r,o=new Set,c=new My.default;c.pipe(r.output??process.stdout),c.mute();let l=u.createInterface({terminal:!0,input:i,output:c}),d=new Ay(l),{promise:f,resolve:p,reject:m}=jy.withResolver(),h=()=>m(new tv);if(a){let e=()=>m(new ev({cause:a.reason}));if(a.aborted)return e(),Object.assign(f,{cancel:h});a.addEventListener(`abort`,e),o.add(()=>a.removeEventListener(`abort`,e))}o.add(yy((e,t)=>{m(new nv(`User force closed the prompt with ${e} ${t}`))}));let g=()=>m(new nv(`User force closed the prompt with SIGINT`));return l.on(`SIGINT`,g),o.add(()=>l.removeListener(`SIGINT`,g)),sv(l,a=>{let u=s.bind(()=>pv.clearAll());l.on(`close`,u),o.add(()=>l.removeListener(`close`,u));let g=()=>{let r=()=>d.checkCursorPos();l.input.on(`keypress`,r),o.add(()=>l.input.removeListener(`keypress`,r)),a(()=>{try{let r=e(n,e=>{setImmediate(()=>p(e))});if(r===void 0){let e=t[1]?.getFileName();throw Error(`Prompt functions must return a string.\n at ${e}`)}let[i,a]=typeof r==`string`?[r]:r;d.render(i,a),pv.run()}catch(e){m(e)}})};return`readableFlowing`in i?Ny(g):g(),Object.assign(f.then(e=>(pv.clearAll(),e),e=>{throw pv.clearAll(),e}).finally(()=>{o.forEach(e=>e()),d.done({clearContent:!!r.clearPromptOnDone}),c.end()}).then(()=>f),{cancel:h})})}}var $=class{separator=l(`dim`,Array.from({length:15}).join(xv.line));type=`separator`;constructor(e){e&&(this.separator=e)}static isSeparator(e){return!!(e&&typeof e==`object`&&`type`in e&&e.type===`separator`)}};const Iy={icon:{checked:l(`green`,xv.circleFilled),unchecked:xv.circle,cursor:xv.pointer,disabledChecked:l(`green`,xv.circleDouble),disabledUnchecked:`-`},style:{disabled:e=>l(`dim`,e),renderSelectedChoices:e=>e.map(e=>e.short).join(`, `),description:e=>l(`cyan`,e),keysHelpTip:e=>e.map(([e,t])=>`${l(`bold`,e)} ${l(`dim`,t)}`).join(l(`dim`,` • `))},i18n:{disabledError:`This option is disabled and cannot be toggled.`},keybindings:[]};function Ly(e){return!$.isSeparator(e)&&!e.disabled}function Ry(e){return!$.isSeparator(e)}function zy(e){return!$.isSeparator(e)&&e.checked}function By(e){return Ly(e)?{...e,checked:!e.checked}:e}function Vy(e){return function(t){return Ly(t)?{...t,checked:e}:t}}function Hy(e){return e.map(e=>{if($.isSeparator(e))return e;if(typeof e==`string`)return{value:e,name:e,short:e,checkedName:e,disabled:!1,checked:!1};let t=e.name??String(e.value),n={value:e.value,name:t,short:e.short??t,checkedName:e.checkedName??t,disabled:e.disabled??!1,checked:e.checked??!1};return e.description&&(n.description=e.description),n})}var Uy=Fy((e,t)=>{let{pageSize:n=7,loop:r=!0,required:i,validate:a=()=>!0}=e,o={all:`a`,invert:`i`,...e.shortcuts},s=Tv(Iy,e.theme),{keybindings:c}=s,[l,u]=Q(`idle`),d=Ev({status:l,theme:s}),[f,p]=Q(Hy(e.choices)),m=Dv(()=>{let e=f.findIndex(Ry),t=f.findLastIndex(Ry);if(e===-1)throw new iv(`[checkbox prompt] No selectable choices. All choices are disabled.`);return{first:e,last:t}},[f]),[h,g]=Q(m.first),[_,v]=Q();kv(async e=>{if($_(e)){let e=f.filter(zy),n=await a([...e]);i&&!e.length?v(`At least one choice must be selected`):n===!0?(u(`done`),t(e.map(e=>e.value))):v(n||`You must select a valid value`)}else if(q_(e,c)||J_(e,c)){if(_&&v(void 0),r||q_(e,c)&&h!==m.first||J_(e,c)&&h!==m.last){let t=q_(e,c)?-1:1,n=h;do n=(n+t+f.length)%f.length;while(!Ry(f[n]));g(n)}}else if(Y_(e)){let e=f[h];e&&!$.isSeparator(e)&&(e.disabled?v(s.i18n.disabledError):(v(void 0),p(f.map((e,t)=>t===h?By(e):e))))}else if(e.name===o.all){let e=f.some(e=>Ly(e)&&!e.checked);p(f.map(Vy(e)))}else if(e.name===o.invert)p(f.map(By));else if(Q_(e)){let t=Number(e.name)-1,n=-1,r=f.findIndex(e=>$.isSeparator(e)?!1:(n++,n===t)),i=f[r];i&&Ly(i)&&(g(r),p(f.map((e,t)=>t===r?By(e):e)))}});let y=s.style.message(e.message,l),b,x=oy({items:f,active:h,renderItem({item:e,isActive:t}){if($.isSeparator(e))return` ${e.separator}`;let n=t?s.icon.cursor:` `;if(e.disabled){let t=typeof e.disabled==`string`?e.disabled:`(disabled)`,r=e.checked?s.icon.disabledChecked:s.icon.disabledUnchecked;return s.style.disabled(`${n}${r} ${e.name} ${t}`)}t&&(b=e.description);let r=e.checked?s.icon.checked:s.icon.unchecked,i=e.checked?e.checkedName:e.name;return(t?s.style.highlight:e=>e)(`${n}${r} ${i}`)},pageSize:n,loop:r});if(l===`done`){let e=f.filter(zy);return[d,y,s.style.answer(s.style.renderSelectedChoices(e,f))].filter(Boolean).join(` `)}let S=[[`↑↓`,`navigate`],[`space`,`select`]];o.all&&S.push([o.all,`all`]),o.invert&&S.push([o.invert,`invert`]),S.push([`⏎`,`submit`]);let C=s.style.keysHelpTip(S);return`${[[d,y].filter(Boolean).join(` `),x,` `,b?s.style.description(b):``,_?s.style.error(_):``,C].filter(Boolean).join(`
|
|
202
202
|
`).trimEnd()}${Sy}`});const Wy={validationFailureMode:`keep`};var Gy=Fy((e,t)=>{let{prefill:n=`tab`}=e,r=Tv(Wy,e.theme),[i,a]=Q(`idle`),[o,s]=Q(String(e.default??``)),[c,l]=Q(),[u,d]=Q(``),f=Ev({status:i,theme:r});async function p(t){let{required:n,pattern:r,patternError:i=`Invalid input`}=e;return n&&!t?`You must provide a value`:r&&!r.test(t)?i:typeof e.validate==`function`?await e.validate(t)||`You must provide a valid value`:!0}kv(async(e,n)=>{if(i===`idle`)if($_(e)){let e=u||o;a(`loading`);let i=await p(e);i===!0?(d(e),a(`done`),t(e)):(r.validationFailureMode===`clear`?d(``):n.write(u),l(i),a(`idle`))}else X_(e)&&!u?s(``):Z_(e)&&!u?(s(``),n.clearLine(0),n.write(o),d(o)):(d(n.line),l(void 0))}),mv(e=>{n===`editable`&&o&&(e.write(o),d(o))},[]);let m=r.style.message(e.message,i),h=u;typeof e.transformer==`function`?h=e.transformer(u,{isFinal:i===`done`}):i===`done`&&(h=r.style.answer(u));let g;o&&i!==`done`&&!u&&(g=r.style.defaultAnswer(o));let _=``;return c&&(_=r.style.error(c)),[[f,m,g,h].filter(e=>e!==void 0).join(` `),_]});const Ky={icon:{cursor:xv.pointer},style:{disabled:e=>l(`dim`,e),description:e=>l(`cyan`,e),keysHelpTip:e=>e.map(([e,t])=>`${l(`bold`,e)} ${l(`dim`,t)}`).join(l(`dim`,` • `))},i18n:{disabledError:`This option is disabled and cannot be selected.`},indexMode:`hidden`,keybindings:[]};function qy(e){return!$.isSeparator(e)&&!e.disabled}function Jy(e){return!$.isSeparator(e)}function Yy(e){return e.map(e=>{if($.isSeparator(e))return e;if(typeof e!=`object`||!e||!(`value`in e)){let t=String(e);return{value:e,name:t,short:t,disabled:!1}}let t=e.name??String(e.value),n={value:e.value,name:t,short:e.short??t,disabled:e.disabled??!1};return e.description&&(n.description=e.description),n})}var Xy=Fy((e,t)=>{let{loop:n=!0,pageSize:r=7}=e,i=Tv(Ky,e.theme),{keybindings:a}=i,[o,s]=Q(`idle`),c=Ev({status:o,theme:i}),l=Ov(),u=!a.includes(`vim`),d=Dv(()=>Yy(e.choices),[e.choices]),f=Dv(()=>{let e=d.findIndex(Jy),t=d.findLastIndex(Jy);if(e===-1)throw new iv(`[select prompt] No selectable choices. All choices are disabled.`);return{first:e,last:t}},[d]),p=Dv(()=>`default`in e?d.findIndex(t=>qy(t)&&t.value===e.default):-1,[e.default,d]),[m,h]=Q(p===-1?f.first:p),g=d[m],[_,v]=Q();kv((e,r)=>{if(clearTimeout(l.current),_&&v(void 0),$_(e))g.disabled?v(i.i18n.disabledError):(s(`done`),t(g.value));else if(q_(e,a)||J_(e,a)){if(r.clearLine(0),n||q_(e,a)&&m!==f.first||J_(e,a)&&m!==f.last){let t=q_(e,a)?-1:1,n=m;do n=(n+t+d.length)%d.length;while(!Jy(d[n]));h(n)}}else if(Q_(e)&&!Number.isNaN(Number(r.line))){let e=Number(r.line)-1,t=-1,n=d.findIndex(n=>$.isSeparator(n)?!1:(t++,t===e)),i=d[n];i!=null&&qy(i)&&h(n),l.current=setTimeout(()=>{r.clearLine(0)},700)}else if(X_(e))r.clearLine(0);else if(u){let e=r.line.toLowerCase(),t=d.findIndex(t=>$.isSeparator(t)||!qy(t)?!1:t.name.toLowerCase().startsWith(e));t!==-1&&h(t),l.current=setTimeout(()=>{r.clearLine(0)},700)}}),mv(()=>()=>{clearTimeout(l.current)},[]);let y=i.style.message(e.message,o),b=i.style.keysHelpTip([[`↑↓`,`navigate`],[`⏎`,`select`]]),x=0,S=oy({items:d,active:m,renderItem({item:e,isActive:t,index:n}){if($.isSeparator(e))return x++,` ${e.separator}`;let r=t?i.icon.cursor:` `,a=i.indexMode===`number`?`${n+1-x}. `:``;if(e.disabled){let n=typeof e.disabled==`string`?e.disabled:`(disabled)`,r=t?i.icon.cursor:`-`;return i.style.disabled(`${r} ${a}${e.name} ${n}`)}return(t?i.style.highlight:e=>e)(`${r} ${a}${e.name}`)},pageSize:r,loop:n});if(o===`done`)return[c,y,i.style.answer(g.short)].filter(Boolean).join(` `);let{description:C}=g;return`${[[c,y].filter(Boolean).join(` `),S,` `,C?i.style.description(C):``,_?i.style.error(_):``,b].filter(Boolean).join(`
|
|
203
|
-
`).trimEnd()}${Sy}`}),Zy=class{static async getText(e){let{message:t,schema:n,default:r}=e,i;if(n&&r!==void 0){let e=n.safeParse(r);e.success&&(i=e.data)}else !n&&r!==void 0&&(i=r);if(n&&n instanceof Af)return await Xy({message:t,choices:n.options.map(e=>({value:e})),default:i});let a=await Gy({message:t,default:i,validate:e=>{if(!n)return!0;let t=e;if(n instanceof Dd){if(e.trim()===``)return`Input cannot be empty`;let n=Number(e);if(Number.isNaN(n))return`Please enter a valid number`;t=n}let r=n.safeParse(t);return r.success?!0:r.error.issues[0]?.message??`Invalid input`}});if(!n)return a;let o=n instanceof Dd?Number(a):a;return n.parse(o)}static async choose(e){let{message:t,options:n,mode:r=`single`,default:i,includeAllOption:a=!1,required:o=!1}=e,s=`__all__`,c=r===`single`?[i]:[...i||[]],l=[...r===`multiple`&&a?[{name:`All`,value:s,checked:c.includes(s)}]:[],...n.map(e=>({name:e,value:e,checked:c.includes(e)}))];if(r===`multiple`){let e=await Uy({message:t,choices:l,validate:e=>o&&e.length===0?`You must select at least one option.`:!0});return a&&e.includes(s)?n:e}return await Xy({message:t,choices:n.map(e=>({name:e,value:e})),default:typeof i==`string`?i:void 0})}},Qy=class e{static command=new vg(`init`).argument(`[projectName]`).option(`-d, --dir <path>`,`workspace directory`).action(e.run.bind(e));static async run(e,t){let n=await H_.getPackageList(),r=n.filter(e=>e.type===`apps`&&e.packageJson?.startx?.mode!==`silent`),i=await this.getPrefs({projectName:e,options:t,projects:r}),a=n.filter(e=>e.type!==`apps`),o=await this.getConfigPrefs({selectedApps:i.selectedApps,packages:a}),s=await this.getPackagesPrefs({selectedPackages:o.selectedConfigs,packages:a,tags:o.gTags}),c=[...s.gTags,`runnable`];await this.installWorkspace({name:i.projectName,tags:[...c,`runnable`],dir:i.directory});let l=[...s.selectedPackages,...i.selectedApps];await Promise.all(l.map(async e=>{let t={},n=new Set(s.gTags);e.packageJson?.startx?.mode===`standalone`&&n.add(`runnable`),e.type===`apps`&&(n.add(`runnable`),s.selectedPackages.filter(t=>t.type!==`packages`||t.packageJson?.startx?.mode===`standalone`?!1:t.packageJson?.startx?.iTags?.every(t=>e.packageJson?.startx?.gTags?.includes(t))).forEach(e=>{let n=e.packageJson?.name||e.name;t[n]=`workspace:^`})),await this.installPackage({pkg:e,directory:i.directory,tags:Array.from(n),dependencies:t})}))}static async getPrefs(e){let n=await Zy.getText({message:`Project name`,name:`projectName`,default:e.projectName,schema:Gp.string().min(1,`Package name is required`).max(214,`Package name too long`).regex(/^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/,`Invalid package name`)});if(e.projects.length===0)throw Error(`No apps found to install.`);let r=H_.getDirectory(),i=e.options.dir?t.resolve(r.workspace,e.options.dir):t.join(r.workspace,n),a=await Zy.choose({message:`Select apps to install`,options:e.projects.map(e=>e.name),includeAllOption:!0,mode:`multiple`,required:!0});return{projectName:n,directory:{workspace:i,template:r.template},selectedApps:e.projects.filter(e=>a.includes(e.name))}}static async getConfigPrefs(e){let t=new Set([`common`]),n=new Map;this.getGlobalTags({pkgs:e.selectedApps}).forEach(e=>t.add(e)),this.getPackageDeps({allPkgs:e.packages,pkgs:e.selectedApps}).forEach(e=>n.set(e.name,e));let r=e.packages.filter(e=>e.type!==`configs`||e.packageJson?.startx?.mode===`silent`||n.has(e.name)?!1:e.packageJson?.startx?.iTags?.every(e=>t.has(e))??!0);if(r.length>0){let e=await Zy.choose({message:`Select configs to install`,options:r.map(e=>e.name),includeAllOption:!0,mode:`multiple`,required:!1});r.filter(t=>e.includes(t.name)).forEach(e=>n.set(e.name,e))}return t.has(`node`)&&(await Zy.choose({message:`Select formatter`,options:[`prettier + biome`,`prettier`],mode:`single`,default:`prettier`,required:!0})===`prettier`||t.add(`biome`),t.add(`prettier`)),this.getPackageDeps({allPkgs:e.packages,pkgs:Array.from(n.values())}).forEach(e=>n.set(e.name,e)),this.getGlobalTags({pkgs:Array.from(n.values())}).forEach(e=>t.add(e)),{gTags:Array.from(t),selectedConfigs:Array.from(n.values())}}static async getPackagesPrefs(e){let t=new Set(e.tags),n=new Map(e.selectedPackages.map(e=>[e.name,e])),r=e.packages.filter(e=>e.type!==`packages`||e.packageJson?.startx?.mode===`silent`||n.has(e.name)?!1:e.packageJson?.startx?.iTags?.every(e=>t.has(e))??!1);if(r.length>0){let e=await Zy.choose({message:`Select packages to install`,options:r.map(e=>e.name),includeAllOption:!0,mode:`multiple`,required:!1});r.filter(t=>e.includes(t.name)).forEach(e=>n.set(e.name,e))}return this.getPackageDeps({allPkgs:e.packages,pkgs:Array.from(n.values())}).forEach(e=>n.set(e.name,e)),this.getGlobalTags({pkgs:Array.from(n.values())}).forEach(e=>t.add(e)),{gTags:Array.from(t),selectedPackages:Array.from(n.values())}}static async installPackage(e){if(!e.pkg.packageJson)throw Error(`Missing package.json for ${e.pkg.name}`);let n=new Set([...e.tags,...e.pkg.packageJson.startx?.tags||[]]),r=e.pkg.packageJson.startx?.ignore||[];r.includes(`eslint-config`)&&n.delete(`eslint`),r.includes(`vitest-config`)&&n.delete(`vitest`);let{packageJson:i,isWorkspace:a}=K_.handlePackageJson({app:e.pkg.packageJson,tags:Array.from(n),name:e.pkg.name,dependencies:e.dependencies});if(a)throw Error(`Cannot install workspace as a package: ${e.pkg.name}`);let o=t.join(e.directory.workspace,e.pkg.relativePath),s=t.join(e.pkg.path);await z_.writeJSONFile({dir:o,file:`package`,content:i}),await this.copyValidatedFilesFromFolder(s,o,n),await z_.copyDirectory({from:t.join(s,`src`),to:t.join(o,`src`),exclude:n.has(`vitest`)?void 0:/\.test\.tsx?$/}),ig.info(`Successfully installed ${e.pkg.name}`)}static async installWorkspace(e){let t=await H_.parsePackageJson({dir:e.dir.template}),n=await H_.parsePackageJson({dir:e.dir.template,file:`startx`});if(!t)throw Error(`Failed to parse root package.json`);t.dependencies={...t.dependencies,...n?.dependencies||{}},t.devDependencies={...t.devDependencies,...n?.devDependencies||{}};let{packageJson:r}=K_.handlePackageJson({app:t,tags:[`root`,...e.tags],name:e.name});await z_.writeJSONFile({dir:e.dir.workspace,file:`package`,content:r}),await this.copyValidatedFilesFromFolder(e.dir.template,e.dir.workspace,new Set([`root`,...e.tags]))}static getPackageDeps(e){let t=new Map(e.pkgs.map(e=>[e.name,e]));return Array.from(t.values()).forEach(n=>{[...n.packageJson?.startx?.requiredDeps||[],...n.packageJson?.startx?.requiredDevDeps||[]].forEach(n=>{let r=e.allPkgs.find(e=>e.packageJson?.name===n);r&&t.set(r.name,r)})}),e.pkgs.forEach(e=>t.delete(e.name)),Array.from(t.values())}static getGlobalTags(e){let t=new Set(e.gTags||[]);return e.pkgs.forEach(e=>{e.packageJson?.startx?.gTags?.forEach(e=>t.add(e))}),Array.from(t)}static async copyValidatedFilesFromFolder(e,n,r){let i=await z_.listFiles({dir:e}).catch(()=>[]);for(let a of i){let i=B_[a];if(!(i&&!i.tags.every(e=>r.has(e))))try{await z_.copyFile({from:t.join(e,a),to:t.join(n,a)})}catch(e){ig.error(`Failed to copy file ${a}:`,e)}}}},$y=`0.
|
|
203
|
+
`).trimEnd()}${Sy}`}),Zy=class{static async getText(e){let{message:t,schema:n,default:r}=e,i;if(n&&r!==void 0){let e=n.safeParse(r);e.success&&(i=e.data)}else !n&&r!==void 0&&(i=r);if(n&&n instanceof Af)return await Xy({message:t,choices:n.options.map(e=>({value:e})),default:i});let a=await Gy({message:t,default:i,validate:e=>{if(!n)return!0;let t=e;if(n instanceof Dd){if(e.trim()===``)return`Input cannot be empty`;let n=Number(e);if(Number.isNaN(n))return`Please enter a valid number`;t=n}let r=n.safeParse(t);return r.success?!0:r.error.issues[0]?.message??`Invalid input`}});if(!n)return a;let o=n instanceof Dd?Number(a):a;return n.parse(o)}static async choose(e){let{message:t,options:n,mode:r=`single`,default:i,includeAllOption:a=!1,required:o=!1}=e,s=`__all__`,c=r===`single`?[i]:[...i||[]],l=[...r===`multiple`&&a?[{name:`All`,value:s,checked:c.includes(s)}]:[],...n.map(e=>({name:e,value:e,checked:c.includes(e)}))];if(r===`multiple`){let e=await Uy({message:t,choices:l,validate:e=>o&&e.length===0?`You must select at least one option.`:!0});return a&&e.includes(s)?n:e}return await Xy({message:t,choices:n.map(e=>({name:e,value:e})),default:typeof i==`string`?i:void 0})}},Qy=class e{static command=new vg(`init`).argument(`[projectName]`).option(`-d, --dir <path>`,`workspace directory`).action(e.run.bind(e));static async run(e,t){let n=await H_.getPackageList(),r=n.filter(e=>e.type===`apps`&&e.packageJson?.startx?.mode!==`silent`),i=await this.getPrefs({projectName:e,options:t,projects:r}),a=n.filter(e=>e.type!==`apps`),o=await this.getConfigPrefs({selectedApps:i.selectedApps,packages:a}),s=await this.getPackagesPrefs({selectedPackages:o.selectedConfigs,packages:a,tags:o.gTags}),c=[...s.gTags,`runnable`];await this.installWorkspace({name:i.projectName,tags:[...c,`runnable`],dir:i.directory});let l=[...s.selectedPackages,...i.selectedApps];await Promise.all(l.map(async e=>{let t={},n=new Set(s.gTags);e.packageJson?.startx?.mode===`standalone`&&n.add(`runnable`),e.type===`apps`&&(n.add(`runnable`),s.selectedPackages.filter(t=>t.type!==`packages`||t.packageJson?.startx?.mode===`standalone`?!1:t.packageJson?.startx?.iTags?.every(t=>e.packageJson?.startx?.gTags?.includes(t))).forEach(e=>{let n=e.packageJson?.name||e.name;t[n]=`workspace:^`})),await this.installPackage({pkg:e,directory:i.directory,tags:Array.from(n),dependencies:t})}))}static async getPrefs(e){let n=await Zy.getText({message:`Project name`,name:`projectName`,default:e.projectName,schema:Gp.string().min(1,`Package name is required`).max(214,`Package name too long`).regex(/^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/,`Invalid package name`)});if(e.projects.length===0)throw Error(`No apps found to install.`);let r=H_.getDirectory(),i=e.options.dir?t.resolve(r.workspace,e.options.dir):t.join(r.workspace,n),a=await Zy.choose({message:`Select apps to install`,options:e.projects.map(e=>e.name),includeAllOption:!0,mode:`multiple`,required:!0});return{projectName:n,directory:{workspace:i,template:r.template},selectedApps:e.projects.filter(e=>a.includes(e.name))}}static async getConfigPrefs(e){let t=new Set([`common`]),n=new Map;this.getGlobalTags({pkgs:e.selectedApps}).forEach(e=>t.add(e)),this.getPackageDeps({allPkgs:e.packages,pkgs:e.selectedApps}).forEach(e=>n.set(e.name,e));let r=e.packages.filter(e=>e.type!==`configs`||e.packageJson?.startx?.mode===`silent`||n.has(e.name)?!1:e.packageJson?.startx?.iTags?.every(e=>t.has(e))??!0);if(r.length>0){let e=await Zy.choose({message:`Select configs to install`,options:r.map(e=>e.name),includeAllOption:!0,mode:`multiple`,required:!1});r.filter(t=>e.includes(t.name)).forEach(e=>n.set(e.name,e))}return t.has(`node`)&&(await Zy.choose({message:`Select formatter`,options:[`prettier + biome`,`prettier`],mode:`single`,default:`prettier`,required:!0})===`prettier`||t.add(`biome`),t.add(`prettier`)),this.getPackageDeps({allPkgs:e.packages,pkgs:Array.from(n.values())}).forEach(e=>n.set(e.name,e)),this.getGlobalTags({pkgs:Array.from(n.values())}).forEach(e=>t.add(e)),{gTags:Array.from(t),selectedConfigs:Array.from(n.values())}}static async getPackagesPrefs(e){let t=new Set(e.tags),n=new Map(e.selectedPackages.map(e=>[e.name,e])),r=e.packages.filter(e=>e.type!==`packages`||e.packageJson?.startx?.mode===`silent`||n.has(e.name)?!1:e.packageJson?.startx?.iTags?.every(e=>t.has(e))??!1);if(r.length>0){let e=await Zy.choose({message:`Select packages to install`,options:r.map(e=>e.name),includeAllOption:!0,mode:`multiple`,required:!1});r.filter(t=>e.includes(t.name)).forEach(e=>n.set(e.name,e))}return this.getPackageDeps({allPkgs:e.packages,pkgs:Array.from(n.values())}).forEach(e=>n.set(e.name,e)),this.getGlobalTags({pkgs:Array.from(n.values())}).forEach(e=>t.add(e)),{gTags:Array.from(t),selectedPackages:Array.from(n.values())}}static async installPackage(e){if(!e.pkg.packageJson)throw Error(`Missing package.json for ${e.pkg.name}`);let n=new Set([...e.tags,...e.pkg.packageJson.startx?.tags||[]]),r=e.pkg.packageJson.startx?.ignore||[];r.includes(`eslint-config`)&&n.delete(`eslint`),r.includes(`vitest-config`)&&n.delete(`vitest`);let{packageJson:i,isWorkspace:a}=K_.handlePackageJson({app:e.pkg.packageJson,tags:Array.from(n),name:e.packageName||e.pkg.packageJson.name||e.pkg.name,dependencies:e.dependencies});if(a)throw Error(`Cannot install workspace as a package: ${e.pkg.name}`);let o=t.join(e.directory.workspace,e.pkg.relativePath),s=t.join(e.pkg.path);await z_.writeJSONFile({dir:o,file:`package`,content:i}),await this.copyValidatedFilesFromFolder(s,o,n),await z_.copyDirectory({from:t.join(s,`src`),to:t.join(o,`src`),exclude:n.has(`vitest`)?void 0:/\.test\.tsx?$/}),ig.info(`Successfully installed ${e.pkg.name}`)}static async installWorkspace(e){let t=await H_.parsePackageJson({dir:e.dir.template}),n=await H_.parsePackageJson({dir:e.dir.template,file:`startx`});if(!t)throw Error(`Failed to parse root package.json`);t.dependencies={...t.dependencies,...n?.dependencies||{}},t.devDependencies={...t.devDependencies,...n?.devDependencies||{}};let{packageJson:r}=K_.handlePackageJson({app:t,tags:[`root`,...e.tags],name:e.name});await z_.writeJSONFile({dir:e.dir.workspace,file:`package`,content:r}),await this.copyValidatedFilesFromFolder(e.dir.template,e.dir.workspace,new Set([`root`,...e.tags]))}static getPackageDeps(e){let t=new Map(e.pkgs.map(e=>[e.name,e]));return Array.from(t.values()).forEach(n=>{[...n.packageJson?.startx?.requiredDeps||[],...n.packageJson?.startx?.requiredDevDeps||[]].forEach(n=>{let r=e.allPkgs.find(e=>e.packageJson?.name===n);r&&t.set(r.name,r)})}),e.pkgs.forEach(e=>t.delete(e.name)),Array.from(t.values())}static getGlobalTags(e){let t=new Set(e.gTags||[]);return e.pkgs.forEach(e=>{e.packageJson?.startx?.gTags?.forEach(e=>t.add(e))}),Array.from(t)}static async copyValidatedFilesFromFolder(e,n,r){let i=await z_.listFiles({dir:e}).catch(()=>[]);for(let a of i){let i=B_[a];if(!(i&&!i.tags.every(e=>r.has(e))))try{await z_.copyFile({from:t.join(e,a),to:t.join(n,a)})}catch(e){ig.error(`Failed to copy file ${a}:`,e)}}}},$y=`1.0.1`;const eb=new vg;eb.name(`startx`).description(`StartX CLI - Your all in one monorepo startup tool.`).version($y),eb.command(`ping`).action(()=>{ig.info(`pong`)}),eb.addCommand(Qy.command),eb.parse(process.argv);export{};
|
|
@@ -225,6 +225,7 @@ export class InitCommand {
|
|
|
225
225
|
|
|
226
226
|
private static async installPackage(props: {
|
|
227
227
|
pkg: PackageItem;
|
|
228
|
+
packageName?: string;
|
|
228
229
|
directory: {
|
|
229
230
|
workspace: string;
|
|
230
231
|
template: string;
|
|
@@ -242,7 +243,7 @@ export class InitCommand {
|
|
|
242
243
|
const { packageJson, isWorkspace } = FileHandler.handlePackageJson({
|
|
243
244
|
app: props.pkg.packageJson,
|
|
244
245
|
tags: Array.from(tags),
|
|
245
|
-
name: props.pkg.name,
|
|
246
|
+
name: props.packageName || props.pkg.packageJson.name || props.pkg.name,
|
|
246
247
|
dependencies: props.dependencies,
|
|
247
248
|
});
|
|
248
249
|
|
|
@@ -86,11 +86,13 @@ export class CliUtils {
|
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
+
const extraPackages = ["@repo", "@db"];
|
|
89
90
|
const results = await Promise.all([
|
|
90
91
|
fetchPackages("apps", "apps"),
|
|
91
92
|
fetchPackages("configs", "configs"),
|
|
92
|
-
fetchPackages("packages", "packages", "", name => name
|
|
93
|
+
fetchPackages("packages", "packages", "", name => !extraPackages.includes(name)),
|
|
93
94
|
fetchPackages("packages/@repo", "packages", "@repo/"),
|
|
95
|
+
fetchPackages("packages/@db", "packages", "@db/"),
|
|
94
96
|
]);
|
|
95
97
|
|
|
96
98
|
return results.flat();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "startx",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/avinashid/startx.git"
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"startx": "node ./apps/startx-cli/dist/index.mjs",
|
|
28
28
|
"backend": "turbo dev --filter=core-server -- ",
|
|
29
29
|
"cli": "turbo cli --filter=cli -- ",
|
|
30
|
+
"startx:cli": "turbo cli --filter=startx-cli -- ",
|
|
30
31
|
"lint": "turbo lint",
|
|
31
32
|
"typecheck": "turbo typecheck",
|
|
32
33
|
"clean": "turbo clean",
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { defineEnv } from "@repo/env";
|
|
2
|
-
import
|
|
2
|
+
import { logger } from "@repo/logger";
|
|
3
|
+
import type { Transporter, SendMailOptions } from "nodemailer";
|
|
3
4
|
import * as nodemailer from "nodemailer";
|
|
4
5
|
import z from "zod";
|
|
5
6
|
|
|
6
|
-
import { logger } from "@repo/logger";
|
|
7
|
-
|
|
8
7
|
const credentials = defineEnv({
|
|
9
8
|
SMTP_HOST: z.string(),
|
|
10
|
-
SMTP_PORT: z.
|
|
9
|
+
SMTP_PORT: z.coerce.number().default(587),
|
|
11
10
|
SMTP_USER: z.string(),
|
|
12
11
|
SMTP_PASSWORD: z.string(),
|
|
13
12
|
SMTP_MAIL_ENCRYPTION: z.string().default("tls"),
|
|
14
|
-
|
|
13
|
+
SMTP_SENDER_MAIL: z.string().email(),
|
|
14
|
+
SMTP_SENDER_NAME: z.string().default("Startx"),
|
|
15
15
|
});
|
|
16
|
+
|
|
16
17
|
class SMTPMailService {
|
|
17
|
-
private static transporter: Transporter;
|
|
18
|
+
private static transporter: Transporter | null = null;
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
private static initializeTransporter() {
|
|
20
|
+
private static initializeTransporter(): Transporter {
|
|
21
21
|
if (!this.transporter) {
|
|
22
22
|
this.transporter = nodemailer.createTransport({
|
|
23
23
|
host: credentials.SMTP_HOST,
|
|
24
|
-
port:
|
|
24
|
+
port: credentials.SMTP_PORT,
|
|
25
25
|
secure: credentials.SMTP_MAIL_ENCRYPTION === "ssl",
|
|
26
26
|
auth: {
|
|
27
27
|
user: credentials.SMTP_USER,
|
|
@@ -29,25 +29,39 @@ class SMTPMailService {
|
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
return this.transporter;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static async verifyConnection(): Promise<void> {
|
|
36
|
+
const transporter = this.initializeTransporter();
|
|
37
|
+
try {
|
|
38
|
+
await transporter.verify();
|
|
39
|
+
logger.info("SMTP Connection verified successfully.");
|
|
40
|
+
} catch (error) {
|
|
41
|
+
logger.error("SMTP Connection verification failed:", error);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
32
44
|
}
|
|
33
45
|
|
|
34
|
-
static async sendMail(to: string
|
|
35
|
-
this.initializeTransporter();
|
|
46
|
+
static async sendMail(props: { to: string; subject: string; text: string; html?: string }) {
|
|
47
|
+
const transporter = this.initializeTransporter();
|
|
36
48
|
|
|
37
|
-
const mailOptions = {
|
|
38
|
-
from: `
|
|
39
|
-
to,
|
|
40
|
-
subject,
|
|
41
|
-
text,
|
|
42
|
-
html,
|
|
49
|
+
const mailOptions: SendMailOptions = {
|
|
50
|
+
from: `"${credentials.SMTP_SENDER_NAME}" <${credentials.SMTP_SENDER_MAIL}>`,
|
|
51
|
+
to: props.to,
|
|
52
|
+
subject: props.subject,
|
|
53
|
+
text: props.text,
|
|
54
|
+
html: props.html,
|
|
43
55
|
};
|
|
44
56
|
|
|
45
57
|
try {
|
|
46
|
-
const info = (await
|
|
47
|
-
logger.info(`Email sent: ${info.messageId}`);
|
|
58
|
+
const info = (await transporter.sendMail(mailOptions)) as { messageId: string };
|
|
59
|
+
logger.info(`Email sent successfully: ${info.messageId}`);
|
|
60
|
+
return info;
|
|
48
61
|
} catch (error) {
|
|
49
62
|
logger.error("Error sending email:", error);
|
|
50
|
-
|
|
63
|
+
// Retain the original error context for debugging
|
|
64
|
+
throw new Error("Failed to send email", { cause: error });
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
67
|
}
|
|
@@ -44,7 +44,12 @@ export class OTPModule {
|
|
|
44
44
|
const html = await EmailTemplate("VerifyEmailOtp", {
|
|
45
45
|
verificationCode: otpStr,
|
|
46
46
|
});
|
|
47
|
-
await SMTPMailService.sendMail(
|
|
47
|
+
await SMTPMailService.sendMail({
|
|
48
|
+
to: email,
|
|
49
|
+
subject: "Verify your email",
|
|
50
|
+
text: `Your verification code is: ${otpStr}`,
|
|
51
|
+
html,
|
|
52
|
+
});
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
static async verifyMailOTP(email: string, otp: string, deleteOtp = false): Promise<boolean> {
|
|
@@ -2,16 +2,17 @@ import { defineEnv } from "@repo/env";
|
|
|
2
2
|
import { logger } from "@repo/logger";
|
|
3
3
|
import { Redis } from "ioredis";
|
|
4
4
|
import z from "zod";
|
|
5
|
-
|
|
5
|
+
const connection = defineEnv({
|
|
6
6
|
REDIS_HOST: z.string().min(1),
|
|
7
|
-
REDIS_PORT: z.number(),
|
|
7
|
+
REDIS_PORT: z.coerce.number(),
|
|
8
8
|
REDIS_USERNAME: z.string(),
|
|
9
9
|
REDIS_PASSWORD: z.string(),
|
|
10
|
+
REDIS_DB: z.coerce.number().optional(),
|
|
10
11
|
});
|
|
11
12
|
|
|
12
13
|
let client: Redis | null = null;
|
|
13
14
|
|
|
14
|
-
export function getRedis() {
|
|
15
|
+
export function getRedis(props?: { db?: number }) {
|
|
15
16
|
if (!client) {
|
|
16
17
|
client = new Redis({
|
|
17
18
|
host: connection.REDIS_HOST,
|
|
@@ -20,6 +21,7 @@ export function getRedis() {
|
|
|
20
21
|
password: connection.REDIS_PASSWORD,
|
|
21
22
|
lazyConnect: true,
|
|
22
23
|
maxRetriesPerRequest: null,
|
|
24
|
+
db: props?.db ?? connection.REDIS_DB ?? 0,
|
|
23
25
|
});
|
|
24
26
|
|
|
25
27
|
client.on("connect", () => {
|
package/packages/aix/src/aix.ts
CHANGED
|
@@ -386,6 +386,7 @@ export class Aix {
|
|
|
386
386
|
schema: Z;
|
|
387
387
|
title?: string;
|
|
388
388
|
description?: string;
|
|
389
|
+
preference?: Partial<AiInterfaceConstructor["preferences"]>;
|
|
389
390
|
}): Promise<{ data: z.infer<Z>; token: { input: number; output: number } }> => {
|
|
390
391
|
try {
|
|
391
392
|
const toolName = props.title || "structure_response";
|
|
@@ -412,7 +413,8 @@ export class Aix {
|
|
|
412
413
|
credentials: props.credentials,
|
|
413
414
|
conversations: [],
|
|
414
415
|
preferences: {
|
|
415
|
-
|
|
416
|
+
...props.preference,
|
|
417
|
+
name: "structure_response_ai",
|
|
416
418
|
type: "worker",
|
|
417
419
|
toolOnly: true,
|
|
418
420
|
temperature: 0.1,
|
|
@@ -421,7 +423,7 @@ export class Aix {
|
|
|
421
423
|
});
|
|
422
424
|
|
|
423
425
|
ai.onEvery(e => {
|
|
424
|
-
|
|
426
|
+
logger.info(e);
|
|
425
427
|
});
|
|
426
428
|
|
|
427
429
|
await ai.tools.attachTools({
|
|
@@ -432,9 +434,17 @@ export class Aix {
|
|
|
432
434
|
|
|
433
435
|
const response = await ai.handleUserMessage(props.message);
|
|
434
436
|
const messages = response.messages;
|
|
435
|
-
|
|
436
|
-
const data = JSON.parse(messages[messages.length - 1].content) as z.infer<Z>;
|
|
437
|
+
const lastMessage = messages[messages.length - 1];
|
|
437
438
|
|
|
439
|
+
if (!lastMessage || !lastMessage.content) {
|
|
440
|
+
throw new Error("AI returned an empty response. Try increasing the token limit.");
|
|
441
|
+
}
|
|
442
|
+
let data: z.infer<Z>;
|
|
443
|
+
try {
|
|
444
|
+
data = JSON.parse(lastMessage.content) as z.infer<Z>;
|
|
445
|
+
} catch (error) {
|
|
446
|
+
throw new Error(`Failed to parse AI response as JSON. Raw output: ${lastMessage.content}`);
|
|
447
|
+
}
|
|
438
448
|
return {
|
|
439
449
|
data,
|
|
440
450
|
token: response.token || { input: 0, output: 0 },
|
|
@@ -19,6 +19,7 @@ export interface AiInterfaceConstructor<T extends AiProvider = AiProvider> {
|
|
|
19
19
|
type: "manager" | "worker";
|
|
20
20
|
toolOnly: boolean;
|
|
21
21
|
temperature?: number;
|
|
22
|
+
maxCompletionTokens?: number;
|
|
22
23
|
seed?: number;
|
|
23
24
|
};
|
|
24
25
|
whitelistedTools?: string[];
|
|
@@ -192,9 +193,7 @@ export abstract class AiInterface<AI, P extends AiProvider> {
|
|
|
192
193
|
isError: res.isError,
|
|
193
194
|
};
|
|
194
195
|
};
|
|
195
|
-
|
|
196
|
-
// const models = await this.ai.
|
|
197
|
-
}
|
|
196
|
+
|
|
198
197
|
// Events
|
|
199
198
|
protected event: IEvent<AiEventType> = new IEvent();
|
|
200
199
|
public on<K extends keyof AiEventType>(event: K, handler: (payload: AiEventType[K]) => void) {
|
|
@@ -38,6 +38,7 @@ export class OpenAIClient extends AiInterface<OpenAI, "openAi"> {
|
|
|
38
38
|
content: e.content,
|
|
39
39
|
})) as unknown as ChatCompletionCreateParamsBase["messages"],
|
|
40
40
|
temperature: this.preferences.temperature,
|
|
41
|
+
max_completion_tokens: this.preferences.maxCompletionTokens,
|
|
41
42
|
...hasAnyTools,
|
|
42
43
|
});
|
|
43
44
|
if (response.usage) {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@repo/queue",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"clean": "rimraf dist .turbo",
|
|
8
|
+
"watch:dev": "pnpm watch",
|
|
9
|
+
"typecheck": "tsc --noEmit",
|
|
10
|
+
"format": "biome format --write .",
|
|
11
|
+
"format:check": "biome ci .",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . --fix",
|
|
14
|
+
"watch": "tsc -p tsconfig.build.json --watch"
|
|
15
|
+
},
|
|
16
|
+
"exports": "./src/index.ts",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/pg": "catalog:",
|
|
19
|
+
"eslint-config": "workspace:*",
|
|
20
|
+
"typescript-config": "workspace:*",
|
|
21
|
+
"vitest-config": "workspace:*"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@repo/env": "workspace:*",
|
|
25
|
+
"@repo/lib": "workspace:*",
|
|
26
|
+
"@repo/logger": "workspace:*",
|
|
27
|
+
"@repo/redis": "workspace:*",
|
|
28
|
+
"bullmq": "catalog:"
|
|
29
|
+
},
|
|
30
|
+
"startx": {
|
|
31
|
+
"iTags": [
|
|
32
|
+
"node"
|
|
33
|
+
],
|
|
34
|
+
"gTags": [
|
|
35
|
+
"ai"
|
|
36
|
+
],
|
|
37
|
+
"tags": [
|
|
38
|
+
"aix"
|
|
39
|
+
],
|
|
40
|
+
"requiredDeps": [
|
|
41
|
+
"@repo/env",
|
|
42
|
+
"@repo/lib",
|
|
43
|
+
"@repo/logger",
|
|
44
|
+
"@repo/redis"
|
|
45
|
+
],
|
|
46
|
+
"requiredDevDeps": [
|
|
47
|
+
"typescript-config"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { logger } from "@repo/logger";
|
|
2
|
+
import { Queue, Worker, QueueEvents, type ConnectionOptions, type JobsOptions } from "bullmq";
|
|
3
|
+
import type { IQueueProvider } from "../queue-interface.js";
|
|
4
|
+
import { JobSchemas, type JobRegistry } from "../registry.js";
|
|
5
|
+
import type { JobOptions, JobHandler, JobContext } from "../types.js";
|
|
6
|
+
|
|
7
|
+
export class BullMQProvider implements IQueueProvider {
|
|
8
|
+
private queues: Map<string, Queue> = new Map();
|
|
9
|
+
private workers: Worker[] = [];
|
|
10
|
+
private events: Map<string, QueueEvents> = new Map();
|
|
11
|
+
|
|
12
|
+
constructor(private connection: ConnectionOptions = { host: "localhost", port: 6379 }) {}
|
|
13
|
+
|
|
14
|
+
private mapOptions(options?: JobOptions): JobsOptions {
|
|
15
|
+
if (!options) return {};
|
|
16
|
+
return {
|
|
17
|
+
jobId: options.jobId,
|
|
18
|
+
delay: options.delay,
|
|
19
|
+
attempts: options.attempts,
|
|
20
|
+
backoff: options.backoff,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private getQueue(queueName: string): Queue {
|
|
25
|
+
if (!this.queues.has(queueName)) {
|
|
26
|
+
this.queues.set(queueName, new Queue(queueName, { connection: this.connection }));
|
|
27
|
+
}
|
|
28
|
+
return this.queues.get(queueName)!;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async enqueue<K extends keyof JobRegistry>(
|
|
32
|
+
queueName: K,
|
|
33
|
+
params: JobRegistry[K]["params"],
|
|
34
|
+
options?: JobOptions
|
|
35
|
+
): Promise<string> {
|
|
36
|
+
const validated = JobSchemas[queueName].params.parse(params);
|
|
37
|
+
const queue = this.getQueue(queueName as string);
|
|
38
|
+
const job = await queue.add("job", validated, this.mapOptions(options));
|
|
39
|
+
return job.id!;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async enqueueMany<K extends keyof JobRegistry>(
|
|
43
|
+
queueName: K,
|
|
44
|
+
paramsList: Array<JobRegistry[K]["params"]>,
|
|
45
|
+
options?: JobOptions
|
|
46
|
+
): Promise<string[]> {
|
|
47
|
+
const queue = this.getQueue(queueName as string);
|
|
48
|
+
const bullOptions = this.mapOptions(options);
|
|
49
|
+
|
|
50
|
+
const jobsToPush = paramsList.map(params => ({
|
|
51
|
+
name: "job",
|
|
52
|
+
data: JobSchemas[queueName].params.parse(params) as JobRegistry[K]["params"],
|
|
53
|
+
opts: bullOptions,
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
const jobs = await queue.addBulk(jobsToPush);
|
|
57
|
+
return jobs.map(j => j.id!);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
registerWorker<K extends keyof JobRegistry>(
|
|
61
|
+
queueName: K,
|
|
62
|
+
handler: JobHandler<JobRegistry[K]["params"], JobRegistry[K]["result"]>,
|
|
63
|
+
options: {
|
|
64
|
+
concurrency?: number;
|
|
65
|
+
}
|
|
66
|
+
): void {
|
|
67
|
+
logger.info(
|
|
68
|
+
`Registering worker for queue ${queueName} with options ${Object.entries(options)
|
|
69
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
70
|
+
.join(", ")}`
|
|
71
|
+
);
|
|
72
|
+
const worker = new Worker(
|
|
73
|
+
queueName as string,
|
|
74
|
+
async job => {
|
|
75
|
+
const validData = JobSchemas[queueName].params.parse(job.data) as JobRegistry[K]["params"];
|
|
76
|
+
|
|
77
|
+
const context: JobContext = {
|
|
78
|
+
jobId: job.id!,
|
|
79
|
+
attemptsMade: job.attemptsMade,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const result = await handler(validData, context);
|
|
83
|
+
return result;
|
|
84
|
+
},
|
|
85
|
+
{ connection: this.connection, concurrency: options.concurrency }
|
|
86
|
+
);
|
|
87
|
+
this.workers.push(worker);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private getQueueEvents(queueName: string): QueueEvents {
|
|
91
|
+
if (!this.events.has(queueName)) {
|
|
92
|
+
this.events.set(queueName, new QueueEvents(queueName, { connection: this.connection }));
|
|
93
|
+
}
|
|
94
|
+
return this.events.get(queueName)!;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
onJobComplete<K extends keyof JobRegistry>(
|
|
98
|
+
queueName: K,
|
|
99
|
+
callback: (jobId: string, result: JobRegistry[K]["result"]) => void
|
|
100
|
+
): void {
|
|
101
|
+
const events = this.getQueueEvents(queueName as string);
|
|
102
|
+
events.on("completed", ({ jobId, returnvalue }) => {
|
|
103
|
+
// Cast the Redis returnvalue to our strongly typed result
|
|
104
|
+
callback(jobId, returnvalue as JobRegistry[K]["result"]);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
onJobFailed<K extends keyof JobRegistry>(queueName: K, callback: (jobId: string, error: Error) => void): void {
|
|
109
|
+
const events = this.getQueueEvents(queueName as string);
|
|
110
|
+
events.on("failed", ({ jobId, failedReason }) => callback(jobId, new Error(failedReason)));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async close(): Promise<void> {
|
|
114
|
+
logger.warn("Shutting down queue system...");
|
|
115
|
+
|
|
116
|
+
await Promise.all(this.workers.map(w => w.close()));
|
|
117
|
+
await Promise.all(Array.from(this.events.values()).map(e => e.close()));
|
|
118
|
+
await Promise.all(Array.from(this.queues.values()).map(q => q.close()));
|
|
119
|
+
|
|
120
|
+
logger.warn("Queue system shut down safely.");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineQueue } from "../types.js";
|
|
3
|
+
|
|
4
|
+
export const emailQueue = defineQueue({
|
|
5
|
+
"email-send": {
|
|
6
|
+
params: z.object({
|
|
7
|
+
to: z.string().email(),
|
|
8
|
+
subject: z.string().min(1),
|
|
9
|
+
text: z.string().optional(),
|
|
10
|
+
html: z.string().optional(),
|
|
11
|
+
}),
|
|
12
|
+
result: z.object({
|
|
13
|
+
messageId: z.string(),
|
|
14
|
+
success: z.boolean(),
|
|
15
|
+
}),
|
|
16
|
+
},
|
|
17
|
+
"email-bounce": {
|
|
18
|
+
params: z.object({
|
|
19
|
+
emailId: z.string(),
|
|
20
|
+
reason: z.string(),
|
|
21
|
+
}),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { JobRegistry } from "./registry.js";
|
|
2
|
+
import type { JobOptions, JobHandler } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export interface IQueueProvider {
|
|
5
|
+
enqueue<K extends keyof JobRegistry>(
|
|
6
|
+
queueName: K,
|
|
7
|
+
params: JobRegistry[K]["params"],
|
|
8
|
+
options?: JobOptions
|
|
9
|
+
): Promise<string>;
|
|
10
|
+
|
|
11
|
+
enqueueMany<K extends keyof JobRegistry>(
|
|
12
|
+
queueName: K,
|
|
13
|
+
paramsList: Array<JobRegistry[K]["params"]>,
|
|
14
|
+
options?: JobOptions
|
|
15
|
+
): Promise<string[]>;
|
|
16
|
+
|
|
17
|
+
registerWorker<K extends keyof JobRegistry>(
|
|
18
|
+
queueName: K,
|
|
19
|
+
handler: JobHandler<JobRegistry[K]["params"], JobRegistry[K]["result"]>,
|
|
20
|
+
options: {
|
|
21
|
+
concurrency?: number;
|
|
22
|
+
}
|
|
23
|
+
): void;
|
|
24
|
+
|
|
25
|
+
onJobComplete<K extends keyof JobRegistry>(
|
|
26
|
+
queueName: K,
|
|
27
|
+
callback: (jobId: string, result: JobRegistry[K]["result"]) => void
|
|
28
|
+
): void;
|
|
29
|
+
|
|
30
|
+
onJobFailed<K extends keyof JobRegistry>(queueName: K, callback: (jobId: string, error: Error) => void): void;
|
|
31
|
+
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { emailQueue } from "./common/email-queue.js";
|
|
3
|
+
|
|
4
|
+
export const JobSchemas = {
|
|
5
|
+
...emailQueue,
|
|
6
|
+
} as const;
|
|
7
|
+
|
|
8
|
+
export type JobRegistry = {
|
|
9
|
+
[K in keyof typeof JobSchemas]: {
|
|
10
|
+
params: z.infer<(typeof JobSchemas)[K]["params"]>;
|
|
11
|
+
result: (typeof JobSchemas)[K] extends { result: infer R extends z.ZodTypeAny } ? z.infer<R> : undefined;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export interface JobOptions {
|
|
4
|
+
jobId?: string;
|
|
5
|
+
delay?: number;
|
|
6
|
+
attempts?: number;
|
|
7
|
+
|
|
8
|
+
backoff?: {
|
|
9
|
+
type: "fixed" | "exponential";
|
|
10
|
+
delay: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface JobContext {
|
|
15
|
+
jobId: string;
|
|
16
|
+
attemptsMade: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type JobHandler<TParams, TResult> = (params: TParams, context: JobContext) => Promise<TResult> | TResult;
|
|
20
|
+
|
|
21
|
+
export type QueueDefinition = Record<string, { params: z.ZodTypeAny; result?: z.ZodTypeAny }>;
|
|
22
|
+
export function defineQueue<T extends QueueDefinition>(definition: T): T {
|
|
23
|
+
return definition;
|
|
24
|
+
}
|
package/pnpm-workspace.yaml
CHANGED
package/startx.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "startx",
|
|
3
3
|
"devDependencies": {
|
|
4
|
-
"@biomejs/biome": "catalog:",
|
|
5
|
-
"prettier": "catalog:",
|
|
6
4
|
"eslint": "catalog:",
|
|
7
5
|
"vitest": "catalog:",
|
|
6
|
+
"@biomejs/biome": "catalog:",
|
|
7
|
+
"prettier": "catalog:",
|
|
8
8
|
"rimraf": "catalog:",
|
|
9
9
|
"turbo": "catalog:",
|
|
10
10
|
"typescript": "catalog:",
|