@coreframe/scripts 0.1.46 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dev.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{readProjectConfig as e}from"./config.js";import{fs as t,net as n}from"./environment.js";import{ProjectPostgresAlreadyRunningError as r,startProjectPostgres as i,stopProjectPostgres as a}from"./db/local-postgres.js";import{ensureDevI18nCatalogs as o}from"./i18n/workflows.js";import{resolveMobileDevHost as s,selectMobileDevDevice as ee}from"./dev-device.js";import{devHttpsCertEnv as te,devHttpsKeyEnv as c,prepareDevHttps as l}from"./dev-https.js";import{acquireDevLock as u}from"./dev-lock.js";import{createDevStartupTiming as d}from"./dev-timing.js";import{managedDevEnv as ne}from"./managed-dev-protocol.js";import{isManagedDevCheckout as re,isPrimaryCheckout as ie}from"./managed-dev.js";import{createTauriDevOutput as ae}from"./tauri-dev-output.js";import f from"node:path";import p from"nano-spawn";import{finished as m}from"node:stream/promises";import*as h from"@clack/prompts";import g from"node:process";import{once as _}from"node:events";import{determineAgent as v}from"@vercel/detect-agent";import{createPrefixStream as y,supervise as b}from"procband";const x=[`web`,`desktop`,`ios`,`android`],S=[`managed-dev-overlay`],C=`VITE_COREFRAME_MANAGED_DEV_OVERLAY_DEBUG`;function w(e){let t=e.dev?.platforms??[`web`];for(let e of t)if(!x.includes(e))throw Error(`Invalid development platform "${String(e)}". Expected one of: ${x.join(`, `)}.`);return[...new Set(t)]}const oe=f.resolve(`node_modules`,`.bin`),T=g.platform===`win32`?`pnpm.cmd`:`pnpm`,se=g.platform===`win32`?`portless.cmd`:`portless`,ce=g.platform===`win32`?`react-router.cmd`:`react-router`,le=g.platform===`win32`?`turso.cmd`:`turso`;async function E({cwd:r=g.cwd(),debug:i,device:a,env:_=g.env,host:x,https:S=!1,interactive:w=g.stdin.isTTY===!0,managed:E=!1,noManaged:F=!1,platform:I=`web`,verbose:de=!1,webPort:L}={}){let R=d({env:_}),fe=_.PATH??_.Path??``,z=I===`web`?P(L??_.COREFRAME_WEB_PORT):void 0,B,V,H,U,W,G=!1,K,q=_;if(E&&F)throw Error(`Cannot use --managed and --no-managed together.`);if(i===`managed-dev-overlay`&&E)throw Error(`Cannot use --managed with --debug managed-dev-overlay.`);if(S&&I!==`web`)throw Error(`Local HTTPS is only supported for the web development platform.`);if(a!==void 0&&I!==`ios`&&I!==`android`)throw Error(`A device name or ID is only supported for iOS or Android development.`);if(I===`web`&&_.TAURI_ENV_PLATFORM!==void 0&&_.COREFRAME_TAURI_DEV!==`1`){let e=_.TAURI_ENV_PLATFORM===`ios`||_.TAURI_ENV_PLATFORM===`android`?_.TAURI_ENV_PLATFORM:`desktop`;throw Error(`Direct Tauri development is not supported. Run \`pnpm dev ${e}\` instead.`)}let J=await R.measure(`dev-lock`,()=>u({cwd:r,interactive:w}));if(!J)return;let Y=()=>{G||(G=!0,V?.kill(`SIGTERM`),W?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),B?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),U?.kill(`SIGTERM`))},X=[`SIGINT`,`SIGTERM`].map(e=>{let t=()=>{K??=e,Y()};return g.on(e,t),{handler:t,signal:e}}),Z=async e=>{let t=b(e);V=t;try{await t.expectSuccess()}catch(e){if(!G)throw e}finally{V===t&&(V=void 0)}};try{let u=I===`ios`||I===`android`?I:void 0,d=u?await ee({env:_,interactive:w,platform:u,target:a}):void 0,O=u&&d?await s({device:d,host:x,interactive:w,platform:u}):void 0,P=O?!0:x,[L,V,K]=await Promise.all([R.measure(`config`,()=>e({cwd:r})),R.measure(`routing`,async()=>I===`web`&&_.PORTLESS!==`0`&&_.TAURI_ENV_PLATFORM===void 0&&!(await v()).isAgent&&await ie(r)),R.measure(`managed`,async()=>i!==`managed-dev-overlay`&&(E||w&&!F)&&await re(r))]);await R.measure(`i18n`,()=>o({cwd:r,projectConfig:L}));let X=await R.measure(`https`,async()=>S&&!V?l({cwd:r}):void 0);q={..._,...R.environment,...i===`managed-dev-overlay`?{[C]:`1`}:void 0,...I===`web`?void 0:{COREFRAME_TAURI_DEV:`1`,TAURI_ENV_PLATFORM:M(I),...O?{TAURI_DEV_HOST:O}:void 0},...X?{[te]:X.cert,[c]:X.key}:void 0};let Q=async()=>{let e=y({label:`web`}),t=y({color:`red`,label:`web`});e.pipe(g.stdout,{end:!1}),t.pipe(g.stderr,{end:!1}),W=p(V?se:ce,V?ue({host:P,port:z}):N({host:P,port:z}),{cwd:r,env:{...q,CLOUDFLARE_ENV:`development`,PATH:oe+f.delimiter+fe},stdin:`inherit`});let n=Promise.allSettled([D(W.stdout,e),D(W.stderr,t)]);try{await W;let e=(await n).find(e=>e.status===`rejected`);if(e)throw e.reason}catch(e){if(!G)throw e}finally{await n,e.end(),t.end(),await Promise.allSettled([m(e),m(t)]),W=void 0}},$=async()=>{if(I===`web`){await Q();return}let e=Q().then(()=>{if(!G)throw Error(`The Vite development server stopped while Tauri was still running.`)}),t,n;if(I===`ios`&&!de){n=y({label:`ios`}),n.pipe(g.stdout,{end:!1});try{t=await ae({output:n}),h.log.info(`Full iOS log: ${t.logFile}`)}catch{n.end(),n=void 0,h.log.warn(`Could not create the temporary iOS log; showing full Tauri output.`)}}B=p(T,j(I,d?.name,O),{cwd:r,env:_,stdio:t?[`inherit`,`pipe`,`pipe`]:`inherit`});let i=t?.consume(B),a=B.catch(async e=>{throw G||(await i,await t?.reportFailure()),e});try{await Promise.race([e,a])}finally{Y(),await Promise.allSettled([e,B,i]),await t?.close(),n?.end(),B=void 0}};if(K&&(q={...q,[ne]:`1`}),G||L.database?.dialect===`sqlite`&&(await R.measure(`database`,async()=>{let e=await n.getAvailablePort(),i=f.resolve(r,`.coreframe`),a=f.join(i,`turso.db`);await t.mkdir(i,{recursive:!0}),q={...q,TURSO_DATABASE_URL:`http://127.0.0.1:${e}`,TURSO_AUTH_TOKEN:`dev`},U=b({name:`turso`,command:le,args:[`dev`,`--port`,String(e),`--db-file`,a],cwd:r,env:_}),await U.waitFor(`listening`)}),await R.measure(`schema`,()=>Z({name:`db`,command:T,args:[`db`,`ensure`],cwd:r,env:q,prefix:!1})),G))return;if(A(L)){let e=y({label:`postgres`});e.pipe(g.stdout,{end:!1});try{let t=await R.measure(`database`,()=>k({config:L,cwd:r,env:q,failIfRunning:!0,interactive:w,isStopping:()=>G,postgresOutput:e,takeoverApproved:J.takeoverApproved}));if(!t)return;H=t,q=t.env;try{G||await R.measure(`schema`,()=>Z({name:`db`,command:T,args:[`db`,`ensure`],cwd:r,env:q,prefix:!1})),G||(R.report(),await $())}finally{await t[Symbol.asyncDispose](),H===t&&(H=void 0)}}finally{e.end()}return}R.report(),await $()}finally{Y();let e;try{await H?.[Symbol.asyncDispose]()}catch(t){e=t}finally{for(let{handler:e,signal:t}of X)g.off(t,e);K&&(g.exitCode??=K===`SIGINT`?130:143)}O(e),await J.release()}}async function D(e,t){for await(let n of e)t.write(`${n}\n`)||await _(t,`drain`)}function O(e){if(e)throw e}async function k({interactive:e,isStopping:t,takeoverApproved:n,...o}){try{return await i(o)}catch(s){if(!(s instanceof r)||!e)throw s;if(!n){let e=await h.confirm({initialValue:!1,message:`PostgreSQL is already running for this project (PID ${s.pid}). Stop it and start here?`});if(h.isCancel(e)||!e){h.cancel(`Keeping the existing PostgreSQL process.`);return}}return await a(s),t()?void 0:i(o)}}function A(e){return(e.database?.dialect??`postgres`)===`postgres`}function j(e,t,n){return[`exec`,`tauri`,...e===`desktop`?[]:[e],`dev`,`--config`,JSON.stringify({build:{beforeDevCommand:``}}),...n===void 0?[]:[`--host=${n}`],...t===void 0?[]:[t]]}function M(e){return e===`desktop`?g.platform===`win32`?`windows`:g.platform:e}function N({host:e,port:t}){return[`dev`,...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e],...t===void 0?[]:[`--port`,String(t)]]}function ue({host:e,port:t}){return[`run`,...t===void 0?[]:[`--app-port`,String(t)],`react-router`,...N({host:e,port:void 0})]}function P(e){if(e===void 0)return;let t=Number(e);if(!Number.isInteger(t)||t<=0||t>65535)throw Error(`COREFRAME_WEB_PORT must be a valid TCP port.`);return t}export{S as devDebugFeatures,x as devPlatforms,C as managedDevOverlayDebugEnv,w as resolveDevPlatforms,E as runDevServer};
2
+ import{readProjectConfig as e}from"./config.js";import{fs as t,net as n}from"./environment.js";import{ProjectPostgresAlreadyRunningError as r,startProjectPostgres as i,stopProjectPostgres as a}from"./db/local-postgres.js";import{ensureDevI18nCatalogs as o}from"./i18n/workflows.js";import{resolveMobileDevHost as s,selectMobileDevDevice as ee}from"./dev-device.js";import{devHttpsCertEnv as te,devHttpsKeyEnv as c,prepareDevHttps as ne}from"./dev-https.js";import{acquireDevLock as l}from"./dev-lock.js";import{createDevStartupTiming as u}from"./dev-timing.js";import{managedDevEnv as re}from"./managed-dev-protocol.js";import{isManagedDevCheckout as ie,isPrimaryCheckout as ae}from"./managed-dev.js";import{createTauriDevOutput as oe}from"./tauri-dev-output.js";import d from"node:path";import f from"nano-spawn";import{finished as p}from"node:stream/promises";import*as m from"@clack/prompts";import h from"node:process";import{once as g}from"node:events";import{determineAgent as _}from"@vercel/detect-agent";import{createPrefixStream as v,supervise as y}from"procband";const b=[`web`,`desktop`,`ios`,`android`],x=[`managed-dev-overlay`],S=`VITE_COREFRAME_MANAGED_DEV_OVERLAY_DEBUG`;function C(e){let t=e.dev?.platforms??[`web`];for(let e of t)if(!b.includes(e))throw Error(`Invalid development platform "${String(e)}". Expected one of: ${b.join(`, `)}.`);return[...new Set(t)]}const se=d.resolve(`node_modules`,`.bin`),w=h.platform===`win32`?`pnpm.cmd`:`pnpm`,ce=h.platform===`win32`?`portless.cmd`:`portless`,le=h.platform===`win32`?`react-router.cmd`:`react-router`,ue=h.platform===`win32`?`turso.cmd`:`turso`;async function T({cwd:r=h.cwd(),debug:i,device:a,env:g=h.env,host:b,https:x=!1,interactive:C=h.stdin.isTTY===!0,managed:T=!1,noManaged:P=!1,platform:F=`web`,verbose:fe=!1,webPort:I}={}){let L=u({env:g}),pe=g.PATH??g.Path??``,R=F===`web`?N(I??g.COREFRAME_WEB_PORT):void 0,z,B,V,H,U,W,G=!1,K,q=g;if(T&&P)throw Error(`Cannot use --managed and --no-managed together.`);if(i===`managed-dev-overlay`&&T)throw Error(`Cannot use --managed with --debug managed-dev-overlay.`);if(x&&F!==`web`)throw Error(`Local HTTPS is only supported for the web development platform.`);if(a!==void 0&&F!==`ios`&&F!==`android`)throw Error(`A device name or ID is only supported for iOS or Android development.`);if(F===`web`&&g.TAURI_ENV_PLATFORM!==void 0&&g.COREFRAME_TAURI_DEV!==`1`){let e=g.TAURI_ENV_PLATFORM===`ios`||g.TAURI_ENV_PLATFORM===`android`?g.TAURI_ENV_PLATFORM:`desktop`;throw Error(`Direct Tauri development is not supported. Run \`pnpm dev ${e}\` instead.`)}let J=await L.measure(`dev-lock`,()=>l({cwd:r,interactive:C}));if(!J)return;let Y=()=>{G||(G=!0,B?.kill(`SIGTERM`),H?.kill(`SIGTERM`),W?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),z?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),U?.kill(`SIGTERM`))},X=[`SIGINT`,`SIGTERM`].map(e=>{let t=()=>{K??=e,Y()};return h.on(e,t),{handler:t,signal:e}}),Z=async e=>{let t=y(e);B=t;try{await t.expectSuccess()}catch(e){if(!G)throw e}finally{B===t&&(B=void 0)}};try{let l=F===`ios`||F===`android`?F:void 0,u=l?await ee({env:g,interactive:C,platform:l,target:a}):void 0,D=l&&u?await s({device:u,host:b,interactive:C,platform:l}):void 0,N=D?!0:b,[I,B,K]=await Promise.all([L.measure(`config`,()=>e({cwd:r})),L.measure(`routing`,async()=>F===`web`&&g.PORTLESS!==`0`&&g.TAURI_ENV_PLATFORM===void 0&&!(await _()).isAgent&&await ae(r)),L.measure(`managed`,async()=>i!==`managed-dev-overlay`&&(T||C&&!P)&&await ie(r))]);await L.measure(`i18n`,()=>o({cwd:r,projectConfig:I}));let X=await L.measure(`https`,async()=>x&&!B?ne({cwd:r}):void 0);q={...g,...L.environment,...i===`managed-dev-overlay`?{[S]:`1`}:void 0,...F===`web`?void 0:{COREFRAME_TAURI_DEV:`1`,TAURI_ENV_PLATFORM:A(F),...D?{TAURI_DEV_HOST:D}:void 0},...X?{[te]:X.cert,[c]:X.key}:void 0};let Q=async()=>{let e=v({label:`web`}),t=v({color:`red`,label:`web`});e.pipe(h.stdout,{end:!1}),t.pipe(h.stderr,{end:!1}),W=f(B?ce:le,B?M({host:N,port:R}):j({host:N,port:R}),{cwd:r,env:{...q,CLOUDFLARE_ENV:`development`,NODE_OPTIONS:[q.NODE_OPTIONS,`--conditions=development`].filter(Boolean).join(` `),PATH:se+d.delimiter+pe},stdin:`inherit`});let n=Promise.allSettled([E(W.stdout,e),E(W.stderr,t)]);try{await W;let e=(await n).find(e=>e.status===`rejected`);if(e)throw e.reason}catch(e){if(!G)throw e}finally{await n,e.end(),t.end(),await Promise.allSettled([p(e),p(t)]),W=void 0}},me=async()=>{if(F===`web`){await Q();return}let e=Q().then(()=>{if(!G)throw Error(`The Vite development server stopped while Tauri was still running.`)}),t,n;if(F===`ios`&&!fe){n=v({label:`ios`}),n.pipe(h.stdout,{end:!1});try{t=await oe({output:n}),m.log.info(`Full iOS log: ${t.logFile}`)}catch{n.end(),n=void 0,m.log.warn(`Could not create the temporary iOS log; showing full Tauri output.`)}}z=f(w,k(F,u?.name,D),{cwd:r,env:g,stdio:t?[`inherit`,`pipe`,`pipe`]:`inherit`});let i=t?.consume(z),a=z.catch(async e=>{throw G||(await i,await t?.reportFailure()),e});try{await Promise.race([e,a])}finally{Y(),await Promise.allSettled([e,z,i]),await t?.close(),n?.end(),z=void 0}},he=async()=>{let e=y({name:`panda`,command:w,args:[`exec`,`panda`,`dev`,`--no-color`],cwd:r,env:q});H=e;try{if(await e.expectSuccess(),!G)throw Error(`The Panda CSS watcher stopped while development was still running.`)}catch(e){if(!G)throw e}finally{H===e&&(H=void 0)}},$=async()=>{let e=he(),t=me();try{await Promise.race([e,t])}finally{Y(),await Promise.allSettled([e,t])}};if(K&&(q={...q,[re]:`1`}),G||I.database?.dialect===`sqlite`&&(await L.measure(`database`,async()=>{let e=await n.getAvailablePort(),i=d.resolve(r,`.coreframe`),a=d.join(i,`turso.db`);await t.mkdir(i,{recursive:!0}),q={...q,TURSO_DATABASE_URL:`http://127.0.0.1:${e}`,TURSO_AUTH_TOKEN:`dev`},U=y({name:`turso`,command:ue,args:[`dev`,`--port`,String(e),`--db-file`,a],cwd:r,env:g}),await U.waitFor(`listening`)}),await L.measure(`schema`,()=>Z({name:`db`,command:w,args:[`db`,`ensure`],cwd:r,env:q,prefix:!1})),G))return;if(O(I)){let e=v({label:`postgres`});e.pipe(h.stdout,{end:!1});try{let t=await L.measure(`database`,()=>de({config:I,cwd:r,env:q,failIfRunning:!0,interactive:C,isStopping:()=>G,postgresOutput:e,takeoverApproved:J.takeoverApproved}));if(!t)return;V=t,q=t.env;try{G||await L.measure(`schema`,()=>Z({name:`db`,command:w,args:[`db`,`ensure`],cwd:r,env:q,prefix:!1})),G||(L.report(),await $())}finally{await t[Symbol.asyncDispose](),V===t&&(V=void 0)}}finally{e.end()}return}L.report(),await $()}finally{Y();let e;try{await V?.[Symbol.asyncDispose]()}catch(t){e=t}finally{for(let{handler:e,signal:t}of X)h.off(t,e);K&&(h.exitCode??=K===`SIGINT`?130:143)}D(e),await J.release()}}async function E(e,t){for await(let n of e)t.write(`${n}\n`)||await g(t,`drain`)}function D(e){if(e)throw e}async function de({interactive:e,isStopping:t,takeoverApproved:n,...o}){try{return await i(o)}catch(s){if(!(s instanceof r)||!e)throw s;if(!n){let e=await m.confirm({initialValue:!1,message:`PostgreSQL is already running for this project (PID ${s.pid}). Stop it and start here?`});if(m.isCancel(e)||!e){m.cancel(`Keeping the existing PostgreSQL process.`);return}}return await a(s),t()?void 0:i(o)}}function O(e){return(e.database?.dialect??`postgres`)===`postgres`}function k(e,t,n){return[`exec`,`tauri`,...e===`desktop`?[]:[e],`dev`,`--config`,JSON.stringify({build:{beforeDevCommand:``}}),...n===void 0?[]:[`--host=${n}`],...t===void 0?[]:[t]]}function A(e){return e===`desktop`?h.platform===`win32`?`windows`:h.platform:e}function j({host:e,port:t}){return[`dev`,...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e],...t===void 0?[]:[`--port`,String(t)]]}function M({host:e,port:t}){return[`run`,...t===void 0?[]:[`--app-port`,String(t)],`react-router`,...j({host:e,port:void 0})]}function N(e){if(e===void 0)return;let t=Number(e);if(!Number.isInteger(t)||t<=0||t>65535)throw Error(`COREFRAME_WEB_PORT must be a valid TCP port.`);return t}export{x as devDebugFeatures,b as devPlatforms,S as managedDevOverlayDebugEnv,C as resolveDevPlatforms,T as runDevServer};
@@ -1 +1 @@
1
- import{readProjectConfig as e}from"../config.js";import{createB2PrivateObjectStore as t}from"../private-object-store.js";import{importProjectDependency as n}from"../project.js";import{assertI18nSegment as r,assertReleaseTag as i,assertRevision as a,resolveProjectArtifact as o}from"./paths.js";import{applyGeneratedTranslations as s,assertCompleteCatalogs as c,catalogRelativePath as l,collectMissingTranslations as u,generateMissingTranslations as d,runLinguiExtract as f,validateLinguiCompile as p,writeRichCatalog as m}from"./catalogs.js";import{ensureImmutableObject as h,materializeObject as g,publishSnapshotManifest as _,readCommitReference as v,readSnapshotManifest as y,sha256File as b,writeSnapshotReferences as x}from"./storage.js";import{access as S,mkdir as C,mkdtemp as w,rename as T,rm as E,stat as D}from"node:fs/promises";import{dirname as O,join as k,resolve as A}from"node:path";import j from"nano-spawn";import{tmpdir as M}from"node:os";async function N({cwd:t=process.cwd(),env:n=process.env}={}){if((await e({cwd:t})).i18n){if(n.COREFRAME_I18N_RELEASE_REVISION){await I({cwd:t,env:n,revision:n.COREFRAME_I18N_RELEASE_REVISION});return}await f(t)}}async function P({cwd:t=process.cwd(),projectConfig:n}={}){let r=n??await e({cwd:t});if(!r.i18n)return;let i=o(t,L(r.i18n).directory);try{if(!(await D(i)).isDirectory())throw Error(`I18n catalog path is not a directory: ${i}.`);return}catch(e){if(e.code!==`ENOENT`)throw e}await f(t)}async function F({cwd:e=process.cwd(),env:t=process.env,store:n,tag:r}){i(r);let a=await R({cwd:e,env:t,store:n});await K(e);let o=await G(e);await q(e,r,o);let l=await w(k(M(),`coreframe-i18n-prepare-`));try{let n=await v({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,revision:o,store:a.store,temporaryDirectory:l});if(n){let e=await y({bucket:a.assets.sourceBucket,cacheRoot:a.cacheRoot,digest:n.snapshot,projectId:a.assets.projectId,store:a.store,temporaryDirectory:l});return W(a,e,o),await B(a,e),await x({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,reference:n,store:a.store,tag:r,temporaryDirectory:l}),{reused:!0,snapshot:n.snapshot}}return await U(a,l,async()=>{let n=await z(a,o,l);n||await H(a),await f(e);let i=await u({config:a.config,cwd:e}),m=await d({config:a.config,cwd:e,env:t,messages:i});await s({config:a.config,cwd:e,missing:i,response:m}),await c({config:a.config,cwd:e}),await p({config:a.config,cwd:e,strict:!0,temporaryDirectory:l});let h=await V(a),g={...n?{baseline:n}:{},catalogs:a.config.catalogs,files:h,generator:i.length>0?a.config.generator?.id??`unconfigured`:`none`,linguiVersion:await J(e),locales:a.config.locales,projectId:a.assets.projectId,revision:o,sourceLocale:a.config.sourceLocale,version:1},v=await _({bucket:a.assets.sourceBucket,manifest:g,projectId:a.assets.projectId,store:a.store,temporaryDirectory:l});return await x({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,reference:{revision:o,snapshot:v,version:1},store:a.store,tag:r,temporaryDirectory:l}),{reused:!1,snapshot:v}})}finally{await E(l,{force:!0,recursive:!0})}}async function I({cwd:t=process.cwd(),env:n=process.env,revision:r,store:i}={}){let o=await e({cwd:t});if(!o.i18n)return;let s=await R({cwd:t,env:n,store:i,projectConfig:o}),c=a(r??await G(t)),l=await w(k(M(),`coreframe-i18n-materialize-`));try{let e=await v({bucket:s.assets.sourceBucket,projectId:s.assets.projectId,revision:c,store:s.store,temporaryDirectory:l});if(!e)throw Error(`No prepared i18n snapshot exists for commit ${c}. Push a v* tag for this commit and wait for the translation gate.`);let t=await y({bucket:s.assets.sourceBucket,cacheRoot:s.cacheRoot,digest:e.snapshot,projectId:s.assets.projectId,store:s.store,temporaryDirectory:l});return W(s,t,c),await B(s,t),{revision:c,snapshot:e.snapshot}}finally{await E(l,{force:!0,recursive:!0})}}function L(e){let t=r(e.sourceLocale,`Source locale`),n=[...new Set(e.locales.map(e=>r(e,`Locale`)))],i=[...new Set(e.catalogs.map(e=>r(e,`Catalog`)))];if(n.length===0||!n.includes(t))throw Error(`I18n locales must include the source locale.`);if(i.length===0)throw Error(`I18n configuration requires at least one catalog.`);if(e.generator&&(!e.generator.command.trim()||!e.generator.id.trim()))throw Error(`I18n generator command and ID must be non-empty.`);return{catalogs:i,directory:e.directory??`locales`,generator:e.generator,locales:n,sourceLocale:t}}async function R({cwd:n=process.cwd(),env:r=process.env,projectConfig:i,store:a}){let o=i??await e({cwd:n});if(!o.i18n)throw Error(`Missing i18n configuration in coreframe.config.ts.`);if(!o.assets)throw Error(`I18n snapshots require the existing private build bucket configured under assets.`);let s=o.assets;return{assets:s,cacheRoot:A(n,`.coreframe`,`i18n`,`cache`),config:L(o.i18n),cwd:A(n),env:r,store:a??t({config:s,env:r})}}async function z(e,t,n){let{stdout:r}=await j(`git`,[`rev-list`,`--first-parent`,`--skip=1`,t],{cwd:e.cwd,stdin:`ignore`});for(let t of r.split(/\r?\n/).filter(Boolean)){let r=await v({bucket:e.assets.sourceBucket,projectId:e.assets.projectId,revision:a(t),store:e.store,temporaryDirectory:n});if(!r)continue;let i=await y({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:r.snapshot,projectId:e.assets.projectId,store:e.store,temporaryDirectory:n});return W(e,i,t),await B(e,i),r.snapshot}}async function B(e,t){for(let n of t.files)if(await g({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:n.digest,projectId:e.assets.projectId,store:e.store,target:o(e.cwd,n.path)}),(await D(o(e.cwd,n.path))).size!==n.size)throw Error(`Materialized i18n artifact size does not match manifest: ${n.path}.`)}async function V(e){let t=[];for(let n of e.config.locales)for(let r of e.config.catalogs){let i=l(e.config,n,r),a=o(e.cwd,i),s=await b(a);await h({bucket:e.assets.sourceBucket,digest:s,projectId:e.assets.projectId,source:a,store:e.store}),t.push({digest:s,path:i,size:(await D(a)).size})}return t.sort((e,t)=>e.path.localeCompare(t.path))}async function H(e){let{stdout:t}=await j(`git`,[`rev-parse`,`--show-prefix`],{cwd:e.cwd,stdin:`ignore`}),r=t.trim(),{stdout:i}=await j(`git`,[`log`,`-1`,`--format=%H`,`--diff-filter=AM`,`--`,`:(top)${`${r}${e.config.directory}/${e.config.sourceLocale}/${e.config.catalogs[0]}.po`}`],{cwd:e.cwd,stdin:`ignore`}),a=i.trim();if(!a)return!1;let s=(await n(`@lingui/format-po`,e.cwd)).formatter({lineNumbers:!1}),c=!1;for(let t of e.config.locales)for(let n of e.config.catalogs){let i=`${r}${`${e.config.directory}/${t}/${n}.po`}`;try{let{stdout:r}=await j(`git`,[`show`,`${a}:${i}`],{cwd:e.cwd,stdin:`ignore`});await m(o(e.cwd,l(e.config,t,n)),s.parse(r)),c=!0}catch{}}return c}async function U(e,t,n){let r=[];for(let n of e.config.locales)for(let i of e.config.catalogs){let a=l(e.config,n,i),s=o(e.cwd,a);try{await S(s)}catch{continue}let c=k(t,`previous-catalogs`,a);await C(O(c),{recursive:!0}),await T(s,c),r.push({backup:c,path:s})}try{let e=await n();return await E(k(t,`previous-catalogs`),{force:!0,recursive:!0}),e}catch(t){for(let t of e.config.locales)for(let n of e.config.catalogs)await E(o(e.cwd,l(e.config,t,n)),{force:!0});for(let{backup:e,path:t}of r)await C(O(t),{recursive:!0}),await T(e,t);throw t}}function W(e,t,n){if(t.revision!==n||t.projectId!==e.assets.projectId||t.sourceLocale!==e.config.sourceLocale||JSON.stringify(t.locales)!==JSON.stringify(e.config.locales)||JSON.stringify(t.catalogs)!==JSON.stringify(e.config.catalogs))throw Error(`I18n snapshot does not match commit or project configuration.`);let r=e.config.locales.flatMap(t=>e.config.catalogs.map(n=>l(e.config,t,n))),i=t.files.map(e=>e.path);if(new Set(i).size!==i.length||JSON.stringify(i.sort())!==JSON.stringify(r.sort()))throw Error(`I18n snapshot has an incomplete or unexpected artifact set.`)}async function G(e){let{stdout:t}=await j(`git`,[`rev-parse`,`HEAD`],{cwd:e,stdin:`ignore`});return a(t.trim())}async function K(e){let{stdout:t}=await j(`git`,[`status`,`--porcelain`],{cwd:e,stdin:`ignore`});if(t.trim())throw Error(`Tagged i18n preparation requires a clean Git tree.`)}async function q(e,t,n){let{stdout:r}=await j(`git`,[`rev-parse`,`${t}^{commit}`],{cwd:e,stdin:`ignore`});if(r.trim()!==n)throw Error(`Release tag ${t} does not point to checked-out commit ${n}.`)}async function J(e){let{stdout:t}=await j(`pnpm`,[`exec`,`lingui`,`--version`],{cwd:e,stdin:`ignore`});return t.trim()}export{N as buildI18n,P as ensureDevI18nCatalogs,I as materializeI18nSnapshot,F as prepareI18nRelease,L as resolveI18nConfig};
1
+ import{readProjectConfig as e}from"../config.js";import{createB2PrivateObjectStore as t}from"../private-object-store.js";import{importProjectDependency as n}from"../project.js";import{assertI18nSegment as r,assertReleaseTag as i,assertRevision as a,resolveProjectArtifact as o}from"./paths.js";import{applyGeneratedTranslations as s,assertCompleteCatalogs as c,catalogRelativePath as l,collectMissingTranslations as u,generateMissingTranslations as d,runLinguiExtract as f,validateLinguiCompile as p,writeRichCatalog as m}from"./catalogs.js";import{ensureImmutableObject as h,materializeObject as g,publishSnapshotManifest as _,readCommitReference as v,readSnapshotManifest as y,sha256File as b,writeSnapshotReferences as x}from"./storage.js";import{access as S,mkdir as C,mkdtemp as w,rename as T,rm as E,stat as D}from"node:fs/promises";import{dirname as O,join as k,resolve as A}from"node:path";import j from"nano-spawn";import{tmpdir as M}from"node:os";async function N({cwd:t=process.cwd(),env:n=process.env}={}){if((await e({cwd:t})).i18n){if(n.COREFRAME_I18N_RELEASE_REVISION){await I({cwd:t,env:n,revision:n.COREFRAME_I18N_RELEASE_REVISION});return}await f(t)}}async function P({cwd:t=process.cwd(),projectConfig:n}={}){let r=n??await e({cwd:t});if(!r.i18n)return;let i=L(r.i18n),a=o(t,i.directory);try{if(!(await D(a)).isDirectory())throw Error(`I18n catalog path is not a directory: ${a}.`)}catch(e){if(e.code!==`ENOENT`)throw e;await f(t);return}for(let e of i.locales)for(let n of i.catalogs)try{if(!(await D(o(t,l(i,e,n)))).isFile())throw Error(`I18n catalog path is not a file: ${e}/${n}.json.`)}catch(e){if(e.code!==`ENOENT`)throw e;await f(t);return}}async function F({cwd:e=process.cwd(),env:t=process.env,store:n,tag:r}){i(r);let a=await R({cwd:e,env:t,store:n});await K(e);let o=await G(e);await q(e,r,o);let l=await w(k(M(),`coreframe-i18n-prepare-`));try{let n=await v({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,revision:o,store:a.store,temporaryDirectory:l});if(n){let e=await y({bucket:a.assets.sourceBucket,cacheRoot:a.cacheRoot,digest:n.snapshot,projectId:a.assets.projectId,store:a.store,temporaryDirectory:l});return W(a,e,o),await B(a,e),await x({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,reference:n,store:a.store,tag:r,temporaryDirectory:l}),{reused:!0,snapshot:n.snapshot}}return await U(a,l,async()=>{let n=await z(a,o,l);n||await H(a),await f(e);let i=await u({config:a.config,cwd:e}),m=await d({config:a.config,cwd:e,env:t,messages:i});await s({config:a.config,cwd:e,missing:i,response:m}),await c({config:a.config,cwd:e}),await p({config:a.config,cwd:e,strict:!0,temporaryDirectory:l});let h=await V(a),g={...n?{baseline:n}:{},catalogs:a.config.catalogs,files:h,generator:i.length>0?a.config.generator?.id??`unconfigured`:`none`,linguiVersion:await J(e),locales:a.config.locales,projectId:a.assets.projectId,revision:o,sourceLocale:a.config.sourceLocale,version:1},v=await _({bucket:a.assets.sourceBucket,manifest:g,projectId:a.assets.projectId,store:a.store,temporaryDirectory:l});return await x({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,reference:{revision:o,snapshot:v,version:1},store:a.store,tag:r,temporaryDirectory:l}),{reused:!1,snapshot:v}})}finally{await E(l,{force:!0,recursive:!0})}}async function I({cwd:t=process.cwd(),env:n=process.env,revision:r,store:i}={}){let o=await e({cwd:t});if(!o.i18n)return;let s=await R({cwd:t,env:n,store:i,projectConfig:o}),c=a(r??await G(t)),l=await w(k(M(),`coreframe-i18n-materialize-`));try{let e=await v({bucket:s.assets.sourceBucket,projectId:s.assets.projectId,revision:c,store:s.store,temporaryDirectory:l});if(!e)throw Error(`No prepared i18n snapshot exists for commit ${c}. Push a v* tag for this commit and wait for the translation gate.`);let t=await y({bucket:s.assets.sourceBucket,cacheRoot:s.cacheRoot,digest:e.snapshot,projectId:s.assets.projectId,store:s.store,temporaryDirectory:l});return W(s,t,c),await B(s,t),{revision:c,snapshot:e.snapshot}}finally{await E(l,{force:!0,recursive:!0})}}function L(e){let t=r(e.sourceLocale,`Source locale`),n=[...new Set(e.locales.map(e=>r(e,`Locale`)))],i=[...new Set(e.catalogs.map(e=>r(e,`Catalog`)))];if(n.length===0||!n.includes(t))throw Error(`I18n locales must include the source locale.`);if(i.length===0)throw Error(`I18n configuration requires at least one catalog.`);if(e.generator&&(!e.generator.command.trim()||!e.generator.id.trim()))throw Error(`I18n generator command and ID must be non-empty.`);return{catalogs:i,directory:e.directory??`locales`,generator:e.generator,locales:n,sourceLocale:t}}async function R({cwd:n=process.cwd(),env:r=process.env,projectConfig:i,store:a}){let o=i??await e({cwd:n});if(!o.i18n)throw Error(`Missing i18n configuration in coreframe.config.ts.`);if(!o.assets)throw Error(`I18n snapshots require the existing private build bucket configured under assets.`);let s=o.assets;return{assets:s,cacheRoot:A(n,`.coreframe`,`i18n`,`cache`),config:L(o.i18n),cwd:A(n),env:r,store:a??t({config:s,env:r})}}async function z(e,t,n){let{stdout:r}=await j(`git`,[`rev-list`,`--first-parent`,`--skip=1`,t],{cwd:e.cwd,stdin:`ignore`});for(let t of r.split(/\r?\n/).filter(Boolean)){let r=await v({bucket:e.assets.sourceBucket,projectId:e.assets.projectId,revision:a(t),store:e.store,temporaryDirectory:n});if(!r)continue;let i=await y({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:r.snapshot,projectId:e.assets.projectId,store:e.store,temporaryDirectory:n});return W(e,i,t),await B(e,i),r.snapshot}}async function B(e,t){for(let n of t.files)if(await g({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:n.digest,projectId:e.assets.projectId,store:e.store,target:o(e.cwd,n.path)}),(await D(o(e.cwd,n.path))).size!==n.size)throw Error(`Materialized i18n artifact size does not match manifest: ${n.path}.`)}async function V(e){let t=[];for(let n of e.config.locales)for(let r of e.config.catalogs){let i=l(e.config,n,r),a=o(e.cwd,i),s=await b(a);await h({bucket:e.assets.sourceBucket,digest:s,projectId:e.assets.projectId,source:a,store:e.store}),t.push({digest:s,path:i,size:(await D(a)).size})}return t.sort((e,t)=>e.path.localeCompare(t.path))}async function H(e){let{stdout:t}=await j(`git`,[`rev-parse`,`--show-prefix`],{cwd:e.cwd,stdin:`ignore`}),r=t.trim(),{stdout:i}=await j(`git`,[`log`,`-1`,`--format=%H`,`--diff-filter=AM`,`--`,`:(top)${`${r}${e.config.directory}/${e.config.sourceLocale}/${e.config.catalogs[0]}.po`}`],{cwd:e.cwd,stdin:`ignore`}),a=i.trim();if(!a)return!1;let s=(await n(`@lingui/format-po`,e.cwd)).formatter({lineNumbers:!1}),c=!1;for(let t of e.config.locales)for(let n of e.config.catalogs){let i=`${r}${`${e.config.directory}/${t}/${n}.po`}`;try{let{stdout:r}=await j(`git`,[`show`,`${a}:${i}`],{cwd:e.cwd,stdin:`ignore`});await m(o(e.cwd,l(e.config,t,n)),s.parse(r)),c=!0}catch{}}return c}async function U(e,t,n){let r=[];for(let n of e.config.locales)for(let i of e.config.catalogs){let a=l(e.config,n,i),s=o(e.cwd,a);try{await S(s)}catch{continue}let c=k(t,`previous-catalogs`,a);await C(O(c),{recursive:!0}),await T(s,c),r.push({backup:c,path:s})}try{let e=await n();return await E(k(t,`previous-catalogs`),{force:!0,recursive:!0}),e}catch(t){for(let t of e.config.locales)for(let n of e.config.catalogs)await E(o(e.cwd,l(e.config,t,n)),{force:!0});for(let{backup:e,path:t}of r)await C(O(t),{recursive:!0}),await T(e,t);throw t}}function W(e,t,n){if(t.revision!==n||t.projectId!==e.assets.projectId||t.sourceLocale!==e.config.sourceLocale||JSON.stringify(t.locales)!==JSON.stringify(e.config.locales)||JSON.stringify(t.catalogs)!==JSON.stringify(e.config.catalogs))throw Error(`I18n snapshot does not match commit or project configuration.`);let r=e.config.locales.flatMap(t=>e.config.catalogs.map(n=>l(e.config,t,n))),i=t.files.map(e=>e.path);if(new Set(i).size!==i.length||JSON.stringify(i.sort())!==JSON.stringify(r.sort()))throw Error(`I18n snapshot has an incomplete or unexpected artifact set.`)}async function G(e){let{stdout:t}=await j(`git`,[`rev-parse`,`HEAD`],{cwd:e,stdin:`ignore`});return a(t.trim())}async function K(e){let{stdout:t}=await j(`git`,[`status`,`--porcelain`],{cwd:e,stdin:`ignore`});if(t.trim())throw Error(`Tagged i18n preparation requires a clean Git tree.`)}async function q(e,t,n){let{stdout:r}=await j(`git`,[`rev-parse`,`${t}^{commit}`],{cwd:e,stdin:`ignore`});if(r.trim()!==n)throw Error(`Release tag ${t} does not point to checked-out commit ${n}.`)}async function J(e){let{stdout:t}=await j(`pnpm`,[`exec`,`lingui`,`--version`],{cwd:e,stdin:`ignore`});return t.trim()}export{N as buildI18n,P as ensureDevI18nCatalogs,I as materializeI18nSnapshot,F as prepareI18nRelease,L as resolveI18nConfig};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreframe/scripts",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/airlock-labs/coreframe.git",