@agimon-ai/doompi-build 0.0.1-alpha.2 → 0.0.1-alpha.4

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.
@@ -1,2 +1,2 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../constants/layout.cjs"),n=require("../identity/index.cjs"),r=require("../generate/index.cjs"),i=require("../syncManifest/index.cjs");let a=require("node:fs");a=e.__toESM(a,1);let o=require("node:path");o=e.__toESM(o,1);function s(e,t){let r=o.default.join(e,t);if(!a.default.existsSync(r))return{};let i={};for(let e of a.default.readdirSync(r)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let r=e.slice(0,-3);i[r===`index`?`index`:n.toKebab(r)]=`${t}/${e}`}return i}function c(){return{name:`doompi-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${o.default.resolve(o.default.dirname(r),e.slice(0,n))}${e.slice(n)}`},load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let i=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(i?{type:`chunk`,id:n,name:o.default.basename(n,o.default.extname(n))}:{type:`asset`,name:o.default.basename(n),source:a.default.readFileSync(n)})};`}}}function l(){return{entry:{"extensions/web":`${t.GENERATED_DIR}/web.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!o.default.isAbsolute(e),plugins:[c()],sourcemap:!0,unbundle:!1}}function u(e={packageDir:process.cwd()}){let n=e.packageDir??process.cwd(),c=r.generateExtension({...e,packageDir:n,check:e.check??!1});for(let e of c.notices)process.stderr.write(`[doompi-build] ${e.path}: ${e.message}\n`);let u={entry:{...s(n,e.exportsDir??`src/exports`),...c.targets.includes(`cli`)?{"extensions/pi":`${t.GENERATED_DIR}/pi.ts`}:{},...c.targets.includes(`server`)?{"extensions/server":`${t.GENERATED_DIR}/server.ts`}:{},...e.entry},clean:!0,dts:{incremental:!0,parallel:!1,eager:!0},exports:!0,format:[`esm`,`cjs`],platform:`node`,sourcemap:!0,unbundle:!0,hooks:{"build:done":()=>void i.writeManifest({packageDir:n,manifest:JSON.parse(a.default.readFileSync(o.default.join(n,`package.json`),`utf8`)),graph:c.graph,targets:c.targets,pluginId:c.pluginId})}};return c.targets.includes(`web`)?[u,l()]:u}exports.doompiExtension=u;
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../constants/layout.cjs"),n=require("../identity/index.cjs"),r=require("../generate/index.cjs"),i=require("../syncManifest/index.cjs");let a=require("node:fs");a=e.__toESM(a,1);let o=require("node:path");o=e.__toESM(o,1);function s(e,t){let r=o.default.join(e,t);if(!a.default.existsSync(r))return{};let i={};for(let e of a.default.readdirSync(r)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let r=e.slice(0,-3);i[r===`index`?`index`:n.toKebab(r)]=`${t}/${e}`}return i}function c(){return{name:`doompi-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${o.default.resolve(o.default.dirname(r),e.slice(0,n))}${e.slice(n)}`},load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let i=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(i?{type:`chunk`,id:n,name:o.default.basename(n,o.default.extname(n))}:{type:`asset`,name:o.default.basename(n),source:a.default.readFileSync(n)})};`}}}function l(){return{entry:{"extensions/web":`${t.GENERATED_DIR}/web.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!o.default.isAbsolute(e),plugins:[c()],sourcemap:!0,unbundle:!1}}function u(e={packageDir:process.cwd()}){let n=e.packageDir??process.cwd(),c=r.generateExtension({...e,packageDir:n,check:e.check??!1});for(let e of c.notices)process.stderr.write(`[doompi-build] ${e.path}: ${e.message}\n`);let u={entry:{...s(n,e.exportsDir??`src/exports`),...c.targets.includes(`cli`)?{"extensions/pi":`${t.GENERATED_DIR}/pi.ts`}:{},...c.targets.includes(`server`)?{"extensions/server":`${t.GENERATED_DIR}/server.ts`}:{},...e.entry},clean:!0,dts:{incremental:!0,parallel:!1,eager:!0},exports:!0,format:[`esm`,`cjs`],platform:`node`,outExtensions:({format:e})=>({js:e===`es`?`.mjs`:`.cjs`,dts:e===`es`?`.d.mts`:`.d.cts`}),sourcemap:!0,unbundle:!0,hooks:{"build:done":()=>void i.writeManifest({packageDir:n,manifest:JSON.parse(a.default.readFileSync(o.default.join(n,`package.json`),`utf8`)),graph:c.graph,targets:c.targets,pluginId:c.pluginId})}};return c.targets.includes(`web`)?[u,l()]:u}exports.doompiExtension=u;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["path","fs","toKebab","GENERATED_DIR","generateExtension","writeManifest"],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { GENERATED_DIR } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { toKebab } from '../identity';\nimport { writeManifest } from '../syncManifest';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n}\n\ninterface PresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: { incremental: boolean; parallel: boolean; eager: boolean };\n exports: boolean;\n format: ('esm' | 'cjs')[];\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n hooks: { 'build:done': () => void };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\n\n/** `src/exports/apiContracts.ts` becomes the `api-contracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem === 'index' ? 'index' : toKebab(stem)] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'doompi-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: fs.readFileSync(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(): BrowserPresetConfig {\n return {\n entry: { 'extensions/web': `${GENERATED_DIR}/web.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n };\n}\n\nexport function doompiExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[doompi-build] ${notice.path}: ${notice.message}\\n`);\n\n const entry: Record<string, string> = {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('cli') ? { 'extensions/pi': `${GENERATED_DIR}/pi.ts` } : {}),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const node: PresetConfig = {\n entry,\n clean: true,\n dts: { incremental: true, parallel: false, eager: true },\n exports: true,\n format: ['esm', 'cjs'],\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Node output uses fixed extensions, so pi.extensions and doompiServer.dist\n // both land on the .mjs filenames their hosts require.\n platform: 'node',\n sourcemap: true,\n unbundle: true,\n hooks: {\n 'build:done': () =>\n void writeManifest({\n packageDir,\n manifest: JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n }),\n },\n };\n\n return result.targets.includes('web') ? [node, browserConfig()] : node;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["path","fs","toKebab","GENERATED_DIR","generateExtension","writeManifest"],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { GENERATED_DIR } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { toKebab } from '../identity';\nimport { writeManifest } from '../syncManifest';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n}\n\ninterface PresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: { incremental: boolean; parallel: boolean; eager: boolean };\n exports: boolean;\n format: ('esm' | 'cjs')[];\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n outExtensions: ({ format }: { format: string }) => {\n js: string;\n dts: string;\n };\n hooks: { 'build:done': () => void };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\n\n/** `src/exports/apiContracts.ts` becomes the `api-contracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem === 'index' ? 'index' : toKebab(stem)] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'doompi-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: fs.readFileSync(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(): BrowserPresetConfig {\n return {\n entry: { 'extensions/web': `${GENERATED_DIR}/web.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n };\n}\n\nexport function doompiExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[doompi-build] ${notice.path}: ${notice.message}\\n`);\n\n const entry: Record<string, string> = {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('cli') ? { 'extensions/pi': `${GENERATED_DIR}/pi.ts` } : {}),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const node: PresetConfig = {\n entry,\n clean: true,\n dts: { incremental: true, parallel: false, eager: true },\n exports: true,\n format: ['esm', 'cjs'],\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Node output uses fixed extensions, so pi.extensions and doompiServer.dist\n // both land on the .mjs filenames their hosts require.\n platform: 'node',\n outExtensions: ({ format }) => ({\n js: format === 'es' ? '.mjs' : '.cjs',\n dts: format === 'es' ? '.d.mts' : '.d.cts',\n }),\n sourcemap: true,\n unbundle: true,\n hooks: {\n 'build:done': () =>\n void writeManifest({\n packageDir,\n manifest: JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n }),\n },\n };\n\n return result.targets.includes('web') ? [node, browserConfig()] : node;\n}\n"],"mappings":"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"}
@@ -40,6 +40,12 @@ interface PresetConfig {
40
40
  platform: 'node';
41
41
  sourcemap: boolean;
42
42
  unbundle: boolean;
43
+ outExtensions: ({ format }: {
44
+ format: string;
45
+ }) => {
46
+ js: string;
47
+ dts: string;
48
+ };
43
49
  hooks: {
44
50
  'build:done': () => void;
45
51
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/tsdownPreset/index.ts"],"mappings":";;UASU;WACC;WACA;WACA;WACA,SAAS;;UAGV;WACC;EACT,UAAU,gBAAgB;EAC1B,KAAK;IAAQ,SAAS,MAAM;KAAwB;;;UAI5C;EACR,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,SAAS;EACT;EACA;;UAGQ;EACR,OAAO;EACP;EACA;IAAO;IAAsB;IAAmB;;EAChD;EACA;EACA;EACA;EACA;EACA;IAAS;;;;;;;;;;;iBA0BM,+BAA+B;;WAErC,QAAQ;;WAER;;wBAqEK,gBACd,UAAS,yBACR,gBAAgB,eAAe"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/tsdownPreset/index.ts"],"mappings":";;UASU;WACC;WACA;WACA;WACA,SAAS;;UAGV;WACC;EACT,UAAU,gBAAgB;EAC1B,KAAK;IAAQ,SAAS,MAAM;KAAwB;;;UAI5C;EACR,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,SAAS;EACT;EACA;;UAGQ;EACR,OAAO;EACP;EACA;IAAO;IAAsB;IAAmB;;EAChD;EACA;EACA;EACA;EACA;EACA,kBAAkB;IAAY;;IAC5B;IACA;;EAEF;IAAS;;;;;;;;;;;iBA0BM,+BAA+B;;WAErC,QAAQ;;WAER;;wBAqEK,gBACd,UAAS,yBACR,gBAAgB,eAAe"}
@@ -40,6 +40,12 @@ interface PresetConfig {
40
40
  platform: 'node';
41
41
  sourcemap: boolean;
42
42
  unbundle: boolean;
43
+ outExtensions: ({ format }: {
44
+ format: string;
45
+ }) => {
46
+ js: string;
47
+ dts: string;
48
+ };
43
49
  hooks: {
44
50
  'build:done': () => void;
45
51
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/services/tsdownPreset/index.ts"],"mappings":";;UASU;WACC;WACA;WACA;WACA,SAAS;;UAGV;WACC;EACT,UAAU,gBAAgB;EAC1B,KAAK;IAAQ,SAAS,MAAM;KAAwB;;;UAI5C;EACR,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,SAAS;EACT;EACA;;UAGQ;EACR,OAAO;EACP;EACA;IAAO;IAAsB;IAAmB;;EAChD;EACA;EACA;EACA;EACA;EACA;IAAS;;;;;;;;;;;iBA0BM,+BAA+B;;WAErC,QAAQ;;WAER;;wBAqEK,gBACd,UAAS,yBACR,gBAAgB,eAAe"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/services/tsdownPreset/index.ts"],"mappings":";;UASU;WACC;WACA;WACA;WACA,SAAS;;UAGV;WACC;EACT,UAAU,gBAAgB;EAC1B,KAAK;IAAQ,SAAS,MAAM;KAAwB;;;UAI5C;EACR,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,SAAS;EACT;EACA;;UAGQ;EACR,OAAO;EACP;EACA;IAAO;IAAsB;IAAmB;;EAChD;EACA;EACA;EACA;EACA;EACA,kBAAkB;IAAY;;IAC5B;IACA;;EAEF;IAAS;;;;;;;;;;;iBA0BM,+BAA+B;;WAErC,QAAQ;;WAER;;wBAqEK,gBACd,UAAS,yBACR,gBAAgB,eAAe"}
@@ -1,2 +1,2 @@
1
- import{GENERATED_DIR as e}from"../../constants/layout.mjs";import{toKebab as t}from"../identity/index.mjs";import{generateExtension as n}from"../generate/index.mjs";import{writeManifest as r}from"../syncManifest/index.mjs";import i from"node:fs";import a from"node:path";function o(e,n){let r=a.join(e,n);if(!i.existsSync(r))return{};let o={};for(let e of i.readdirSync(r)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let r=e.slice(0,-3);o[r===`index`?`index`:t(r)]=`${n}/${e}`}return o}function s(){return{name:`doompi-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${a.resolve(a.dirname(r),e.slice(0,n))}${e.slice(n)}`},load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let o=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(o?{type:`chunk`,id:n,name:a.basename(n,a.extname(n))}:{type:`asset`,name:a.basename(n),source:i.readFileSync(n)})};`}}}function c(){return{entry:{"extensions/web":`${e}/web.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!a.isAbsolute(e),plugins:[s()],sourcemap:!0,unbundle:!1}}function l(t={packageDir:process.cwd()}){let s=t.packageDir??process.cwd(),l=n({...t,packageDir:s,check:t.check??!1});for(let e of l.notices)process.stderr.write(`[doompi-build] ${e.path}: ${e.message}\n`);let u={entry:{...o(s,t.exportsDir??`src/exports`),...l.targets.includes(`cli`)?{"extensions/pi":`${e}/pi.ts`}:{},...l.targets.includes(`server`)?{"extensions/server":`${e}/server.ts`}:{},...t.entry},clean:!0,dts:{incremental:!0,parallel:!1,eager:!0},exports:!0,format:[`esm`,`cjs`],platform:`node`,sourcemap:!0,unbundle:!0,hooks:{"build:done":()=>void r({packageDir:s,manifest:JSON.parse(i.readFileSync(a.join(s,`package.json`),`utf8`)),graph:l.graph,targets:l.targets,pluginId:l.pluginId})}};return l.targets.includes(`web`)?[u,c()]:u}export{l as doompiExtension};
1
+ import{GENERATED_DIR as e}from"../../constants/layout.mjs";import{toKebab as t}from"../identity/index.mjs";import{generateExtension as n}from"../generate/index.mjs";import{writeManifest as r}from"../syncManifest/index.mjs";import i from"node:fs";import a from"node:path";function o(e,n){let r=a.join(e,n);if(!i.existsSync(r))return{};let o={};for(let e of i.readdirSync(r)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let r=e.slice(0,-3);o[r===`index`?`index`:t(r)]=`${n}/${e}`}return o}function s(){return{name:`doompi-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${a.resolve(a.dirname(r),e.slice(0,n))}${e.slice(n)}`},load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let o=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(o?{type:`chunk`,id:n,name:a.basename(n,a.extname(n))}:{type:`asset`,name:a.basename(n),source:i.readFileSync(n)})};`}}}function c(){return{entry:{"extensions/web":`${e}/web.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!a.isAbsolute(e),plugins:[s()],sourcemap:!0,unbundle:!1}}function l(t={packageDir:process.cwd()}){let s=t.packageDir??process.cwd(),l=n({...t,packageDir:s,check:t.check??!1});for(let e of l.notices)process.stderr.write(`[doompi-build] ${e.path}: ${e.message}\n`);let u={entry:{...o(s,t.exportsDir??`src/exports`),...l.targets.includes(`cli`)?{"extensions/pi":`${e}/pi.ts`}:{},...l.targets.includes(`server`)?{"extensions/server":`${e}/server.ts`}:{},...t.entry},clean:!0,dts:{incremental:!0,parallel:!1,eager:!0},exports:!0,format:[`esm`,`cjs`],platform:`node`,outExtensions:({format:e})=>({js:e===`es`?`.mjs`:`.cjs`,dts:e===`es`?`.d.mts`:`.d.cts`}),sourcemap:!0,unbundle:!0,hooks:{"build:done":()=>void r({packageDir:s,manifest:JSON.parse(i.readFileSync(a.join(s,`package.json`),`utf8`)),graph:l.graph,targets:l.targets,pluginId:l.pluginId})}};return l.targets.includes(`web`)?[u,c()]:u}export{l as doompiExtension};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { GENERATED_DIR } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { toKebab } from '../identity';\nimport { writeManifest } from '../syncManifest';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n}\n\ninterface PresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: { incremental: boolean; parallel: boolean; eager: boolean };\n exports: boolean;\n format: ('esm' | 'cjs')[];\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n hooks: { 'build:done': () => void };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\n\n/** `src/exports/apiContracts.ts` becomes the `api-contracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem === 'index' ? 'index' : toKebab(stem)] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'doompi-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: fs.readFileSync(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(): BrowserPresetConfig {\n return {\n entry: { 'extensions/web': `${GENERATED_DIR}/web.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n };\n}\n\nexport function doompiExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[doompi-build] ${notice.path}: ${notice.message}\\n`);\n\n const entry: Record<string, string> = {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('cli') ? { 'extensions/pi': `${GENERATED_DIR}/pi.ts` } : {}),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const node: PresetConfig = {\n entry,\n clean: true,\n dts: { incremental: true, parallel: false, eager: true },\n exports: true,\n format: ['esm', 'cjs'],\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Node output uses fixed extensions, so pi.extensions and doompiServer.dist\n // both land on the .mjs filenames their hosts require.\n platform: 'node',\n sourcemap: true,\n unbundle: true,\n hooks: {\n 'build:done': () =>\n void writeManifest({\n packageDir,\n manifest: JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n }),\n },\n };\n\n return result.targets.includes('web') ? [node, browserConfig()] : node;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { GENERATED_DIR } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { toKebab } from '../identity';\nimport { writeManifest } from '../syncManifest';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n}\n\ninterface PresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: { incremental: boolean; parallel: boolean; eager: boolean };\n exports: boolean;\n format: ('esm' | 'cjs')[];\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n outExtensions: ({ format }: { format: string }) => {\n js: string;\n dts: string;\n };\n hooks: { 'build:done': () => void };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\n\n/** `src/exports/apiContracts.ts` becomes the `api-contracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem === 'index' ? 'index' : toKebab(stem)] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'doompi-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: fs.readFileSync(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(): BrowserPresetConfig {\n return {\n entry: { 'extensions/web': `${GENERATED_DIR}/web.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n };\n}\n\nexport function doompiExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[doompi-build] ${notice.path}: ${notice.message}\\n`);\n\n const entry: Record<string, string> = {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('cli') ? { 'extensions/pi': `${GENERATED_DIR}/pi.ts` } : {}),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const node: PresetConfig = {\n entry,\n clean: true,\n dts: { incremental: true, parallel: false, eager: true },\n exports: true,\n format: ['esm', 'cjs'],\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Node output uses fixed extensions, so pi.extensions and doompiServer.dist\n // both land on the .mjs filenames their hosts require.\n platform: 'node',\n outExtensions: ({ format }) => ({\n js: format === 'es' ? '.mjs' : '.cjs',\n dts: format === 'es' ? '.d.mts' : '.d.cts',\n }),\n sourcemap: true,\n unbundle: true,\n hooks: {\n 'build:done': () =>\n void writeManifest({\n packageDir,\n manifest: JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n }),\n },\n };\n\n return result.targets.includes('web') ? [node, browserConfig()] : node;\n}\n"],"mappings":"+QAwDA,SAAS,EAAc,EAAoB,EAA4C,CACrF,IAAM,EAAW,EAAK,KAAK,EAAY,CAAU,EACjD,GAAI,CAAC,EAAG,WAAW,CAAQ,EAAG,MAAO,CAAC,EACtC,IAAM,EAAkC,CAAC,EACzC,IAAK,IAAM,KAAQ,EAAG,YAAY,CAAQ,EAAG,CAC3C,GAAI,CAAC,EAAK,SAAS,KAAK,GAAK,EAAK,SAAS,OAAO,EAAG,SACrD,IAAM,EAAO,EAAK,MAAM,EAAG,EAAa,EACxC,EAAQ,IAAS,QAAU,QAAU,EAAQ,CAAI,GAAK,GAAG,EAAW,GAAG,GACzE,CACA,OAAO,CACT,CAwBA,SAAS,GAAqC,CAC5C,MAAO,CACL,KAAM,sBACN,UAAU,EAAQ,EAAU,CAC1B,IAAM,EAAU,EAAO,QAAQ,GAAG,EAClC,GAAI,EAAU,GAAK,IAAa,IAAA,IAAa,CAAC,EAAO,WAAW,GAAG,EAAG,OACtE,IAAM,EAAe,EAAS,MAAM,GAAG,CAAC,CAAC,GACzC,MAAO,GAAG,EAAK,QAAQ,EAAK,QAAQ,CAAY,EAAG,EAAO,MAAM,EAAG,CAAO,CAAC,IAAI,EAAO,MAAM,CAAO,GACrG,EACA,KAAK,EAAI,CACP,IAAM,EAAU,EAAG,QAAQ,GAAG,EAC9B,GAAI,EAAU,EAAG,OACjB,IAAM,EAAO,EAAG,MAAM,EAAG,CAAO,EAC1B,EAAQ,IAAI,gBAAgB,EAAG,MAAM,EAAU,CAAC,CAAC,EACvD,GAAI,CAAC,EAAM,IAAI,KAAK,EAAG,OACvB,IAAM,EAAS,EAAM,IAAI,QAAQ,EAMjC,MAAO,8CALW,KAAK,SACrB,EACI,CAAE,KAAM,QAAS,GAAI,EAAM,KAAM,EAAK,SAAS,EAAM,EAAK,QAAQ,CAAI,CAAC,CAAE,EACzE,CAAE,KAAM,QAAS,KAAM,EAAK,SAAS,CAAI,EAAG,OAAQ,EAAG,aAAa,CAAI,CAAE,CAEnB,EAAE,EACjE,CACF,CACF,CAGA,SAAS,GAAqC,CAC5C,MAAO,CACL,MAAO,CAAE,iBAAkB,GAAG,EAAc,QAAS,EACrD,MAAO,GAIP,IAAK,GACL,QAAS,GACT,OAAQ,CAAC,KAAK,EACd,SAAU,UAGV,eAAgB,GAShB,SAAW,GAAe,CAAC,EAAG,WAAW,GAAG,GAAK,CAAC,EAAK,WAAW,CAAE,EACpE,QAAS,CAAC,EAAiB,CAAC,EAC5B,UAAW,GAIX,SAAU,EACZ,CACF,CAEA,SAAgB,EACd,EAAkC,CAAE,WAAY,QAAQ,IAAI,CAAE,EACP,CACvD,IAAM,EAAa,EAAQ,YAAc,QAAQ,IAAI,EAC/C,EAAS,EAAkB,CAAE,GAAG,EAAS,aAAY,MAAO,EAAQ,OAAS,EAAM,CAAC,EAE1F,IAAK,IAAM,KAAU,EAAO,QAAS,QAAQ,OAAO,MAAM,kBAAkB,EAAO,KAAK,IAAI,EAAO,QAAQ,GAAG,EAS9G,IAAM,EAAqB,CACzB,MAAA,CAPA,GAAG,EAAc,EAAY,EAAQ,YAAc,aAAmB,EACtE,GAAI,EAAO,QAAQ,SAAS,KAAK,EAAI,CAAE,gBAAiB,GAAG,EAAc,OAAQ,EAAI,CAAC,EACtF,GAAI,EAAO,QAAQ,SAAS,QAAQ,EAAI,CAAE,oBAAqB,GAAG,EAAc,WAAY,EAAI,CAAC,EACjG,GAAG,EAAQ,KAIP,EACJ,MAAO,GACP,IAAK,CAAE,YAAa,GAAM,SAAU,GAAO,MAAO,EAAK,EACvD,QAAS,GACT,OAAQ,CAAC,MAAO,KAAK,EAKrB,SAAU,OACV,eAAgB,CAAE,aAAc,CAC9B,GAAI,IAAW,KAAO,OAAS,OAC/B,IAAK,IAAW,KAAO,SAAW,QACpC,GACA,UAAW,GACX,SAAU,GACV,MAAO,CACL,iBACE,KAAK,EAAc,CACjB,aACA,SAAU,KAAK,MAAM,EAAG,aAAa,EAAK,KAAK,EAAY,cAAc,EAAG,MAAM,CAAC,EAInF,MAAO,EAAO,MACd,QAAS,EAAO,QAChB,SAAU,EAAO,QACnB,CAAC,CACL,CACF,EAEA,OAAO,EAAO,QAAQ,SAAS,KAAK,EAAI,CAAC,EAAM,EAAc,CAAC,EAAI,CACpE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-build",
3
- "version": "0.0.1-alpha.2",
3
+ "version": "0.0.1-alpha.4",
4
4
  "description": "Folder-convention scanner and build presets for DoomPi extensions.",
5
5
  "keywords": [
6
6
  "ai",