@hkonda/loco-translate 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +284 -0
- package/bin/loco.js +5 -0
- package/dist/assets/index-CGo6e-bA.js +59 -0
- package/dist/assets/index-DBcQDZ75.css +1 -0
- package/dist/index.html +13 -0
- package/dist-server/app.d.ts +3 -0
- package/dist-server/app.d.ts.map +1 -0
- package/dist-server/app.js +154 -0
- package/dist-server/app.js.map +1 -0
- package/dist-server/config.d.ts +16 -0
- package/dist-server/config.d.ts.map +1 -0
- package/dist-server/config.js +41 -0
- package/dist-server/config.js.map +1 -0
- package/dist-server/db/index.d.ts +8 -0
- package/dist-server/db/index.d.ts.map +1 -0
- package/dist-server/db/index.js +28 -0
- package/dist-server/db/index.js.map +1 -0
- package/dist-server/db/schema.d.ts +851 -0
- package/dist-server/db/schema.d.ts.map +1 -0
- package/dist-server/db/schema.js +65 -0
- package/dist-server/db/schema.js.map +1 -0
- package/dist-server/db/seed.d.ts +14 -0
- package/dist-server/db/seed.d.ts.map +1 -0
- package/dist-server/db/seed.js +229 -0
- package/dist-server/db/seed.js.map +1 -0
- package/dist-server/index.d.ts +2 -0
- package/dist-server/index.d.ts.map +1 -0
- package/dist-server/index.js +31 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/routes/ai-jobs.d.ts +5 -0
- package/dist-server/routes/ai-jobs.d.ts.map +1 -0
- package/dist-server/routes/ai-jobs.js +141 -0
- package/dist-server/routes/ai-jobs.js.map +1 -0
- package/dist-server/routes/backup.d.ts +5 -0
- package/dist-server/routes/backup.d.ts.map +1 -0
- package/dist-server/routes/backup.js +125 -0
- package/dist-server/routes/backup.js.map +1 -0
- package/dist-server/routes/chrome-extension.d.ts +5 -0
- package/dist-server/routes/chrome-extension.d.ts.map +1 -0
- package/dist-server/routes/chrome-extension.js +140 -0
- package/dist-server/routes/chrome-extension.js.map +1 -0
- package/dist-server/routes/export.d.ts +5 -0
- package/dist-server/routes/export.d.ts.map +1 -0
- package/dist-server/routes/export.js +95 -0
- package/dist-server/routes/export.js.map +1 -0
- package/dist-server/routes/languages.d.ts +5 -0
- package/dist-server/routes/languages.d.ts.map +1 -0
- package/dist-server/routes/languages.js +36 -0
- package/dist-server/routes/languages.js.map +1 -0
- package/dist-server/routes/project.d.ts +5 -0
- package/dist-server/routes/project.d.ts.map +1 -0
- package/dist-server/routes/project.js +151 -0
- package/dist-server/routes/project.js.map +1 -0
- package/dist-server/routes/prompts.d.ts +5 -0
- package/dist-server/routes/prompts.d.ts.map +1 -0
- package/dist-server/routes/prompts.js +90 -0
- package/dist-server/routes/prompts.js.map +1 -0
- package/dist-server/routes/screenshots.d.ts +5 -0
- package/dist-server/routes/screenshots.d.ts.map +1 -0
- package/dist-server/routes/screenshots.js +71 -0
- package/dist-server/routes/screenshots.js.map +1 -0
- package/dist-server/routes/textnodes.d.ts +5 -0
- package/dist-server/routes/textnodes.d.ts.map +1 -0
- package/dist-server/routes/textnodes.js +318 -0
- package/dist-server/routes/textnodes.js.map +1 -0
- package/dist-server/routes/translations.d.ts +5 -0
- package/dist-server/routes/translations.d.ts.map +1 -0
- package/dist-server/routes/translations.js +224 -0
- package/dist-server/routes/translations.js.map +1 -0
- package/dist-server/scripts/backup.d.ts +2 -0
- package/dist-server/scripts/backup.d.ts.map +1 -0
- package/dist-server/scripts/backup.js +26 -0
- package/dist-server/scripts/backup.js.map +1 -0
- package/dist-server/services/ai-translation.d.ts +21 -0
- package/dist-server/services/ai-translation.d.ts.map +1 -0
- package/dist-server/services/ai-translation.js +137 -0
- package/dist-server/services/ai-translation.js.map +1 -0
- package/dist-server/services/job-manager.d.ts +67 -0
- package/dist-server/services/job-manager.d.ts.map +1 -0
- package/dist-server/services/job-manager.js +159 -0
- package/dist-server/services/job-manager.js.map +1 -0
- package/dist-server/services/slot-pattern.d.ts +16 -0
- package/dist-server/services/slot-pattern.d.ts.map +1 -0
- package/dist-server/services/slot-pattern.js +68 -0
- package/dist-server/services/slot-pattern.js.map +1 -0
- package/dist-server/utils/network.d.ts +2 -0
- package/dist-server/utils/network.d.ts.map +1 -0
- package/dist-server/utils/network.js +16 -0
- package/dist-server/utils/network.js.map +1 -0
- package/package.json +47 -0
- package/public/loco.js +2386 -0
- package/public/loco.min.js +4 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-amber-50:oklch(98.7% .022 95.277);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-700:oklch(55.4% .135 66.442);--color-green-50:oklch(98.2% .018 155.826);--color-green-300:oklch(87.1% .15 154.449);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-800:oklch(39.8% .195 277.366);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-1\/2{top:50%}.top-2\.5{top:calc(var(--spacing) * 2.5)}.right-0{right:calc(var(--spacing) * 0)}.right-2{right:calc(var(--spacing) * 2)}.left-2\.5{left:calc(var(--spacing) * 2.5)}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.my-4{margin-block:calc(var(--spacing) * 4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.inline-table{display:inline-table}.list-item{display:list-item}.table{display:table}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-column{display:table-column}.table-column-group{display:table-column-group}.table-footer-group{display:table-footer-group}.table-header-group{display:table-header-group}.table-row{display:table-row}.table-row-group{display:table-row-group}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-\[160px\]{height:160px}.h-full{height:100%}.max-h-24{max-height:calc(var(--spacing) * 24)}.max-h-64{max-height:calc(var(--spacing) * 64)}.min-h-screen{min-height:100vh}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-7{width:calc(var(--spacing) * 7)}.w-10{width:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.w-14{width:calc(var(--spacing) * 14)}.w-56{width:calc(var(--spacing) * 56)}.w-\[280px\]{width:280px}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-\[180px\]{max-width:180px}.max-w-\[250px\]{max-width:250px}.max-w-\[280px\]{max-width:280px}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[90px\]{min-width:90px}.min-w-\[220px\]{min-width:220px}.flex-1{flex:1}.flex-\[2\]{flex:2}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.translate-x-1{--tw-translate-x:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-6{--tw-translate-x:calc(var(--spacing) * 6);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-y{resize:vertical}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0{gap:calc(var(--spacing) * 0)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-gray-100>:not(:last-child)){border-color:var(--color-gray-100)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.rounded-l-md{border-top-left-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.rounded-r-md{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.rounded-b-md{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r-0{border-right-style:var(--tw-border-style);border-right-width:0}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-blue-200{border-color:var(--color-blue-200)}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-700{border-color:var(--color-gray-700)}.border-green-300{border-color:var(--color-green-300)}.border-indigo-200{border-color:var(--color-indigo-200)}.border-indigo-300{border-color:var(--color-indigo-300)}.border-indigo-600{border-color:var(--color-indigo-600)}.border-red-100{border-color:var(--color-red-100)}.border-red-200{border-color:var(--color-red-200)}.border-red-300{border-color:var(--color-red-300)}.border-transparent{border-color:#0000}.bg-amber-50{background-color:var(--color-amber-50)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.bg-black\/40{background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-300{background-color:var(--color-gray-300)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-600{background-color:var(--color-green-600)}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-indigo-100{background-color:var(--color-indigo-100)}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-red-600{background-color:var(--color-red-600)}.bg-red-700{background-color:var(--color-red-700)}.bg-white{background-color:var(--color-white)}.bg-yellow-600{background-color:var(--color-yellow-600)}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-blue-500{--tw-gradient-from:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-yellow-500{--tw-gradient-to:var(--color-yellow-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-10{padding-inline:calc(var(--spacing) * 10)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-10{padding-right:calc(var(--spacing) * 10)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-blue-800{color:var(--color-blue-800)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-green-600{color:var(--color-green-600)}.text-green-700{color:var(--color-green-700)}.text-indigo-600{color:var(--color-indigo-600)}.text-indigo-700{color:var(--color-indigo-700)}.text-red-600{color:var(--color-red-600)}.text-white{color:var(--color-white)}.text-yellow-600{color:var(--color-yellow-600)}.text-yellow-700{color:var(--color-yellow-700)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.line-through{text-decoration-line:line-through}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-all{-webkit-user-select:all;user-select:all}@media (hover:hover){.hover\:border-gray-300:hover{border-color:var(--color-gray-300)}.hover\:border-indigo-200:hover{border-color:var(--color-indigo-200)}.hover\:border-red-300:hover{border-color:var(--color-red-300)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-800:hover{background-color:var(--color-gray-800)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-red-800:hover{background-color:var(--color-red-800)}.hover\:bg-yellow-700:hover{background-color:var(--color-yellow-700)}.hover\:text-gray-600:hover{color:var(--color-gray-600)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-indigo-500:hover{color:var(--color-indigo-500)}.hover\:text-indigo-800:hover{color:var(--color-indigo-800)}.hover\:text-red-500:hover{color:var(--color-red-500)}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}}.focus\:border-indigo-500:focus{border-color:var(--color-indigo-500)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-indigo-300:focus{--tw-ring-color:var(--color-indigo-300)}.focus\:ring-indigo-500:focus{--tw-ring-color:var(--color-indigo-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}.pve.svelte-19itaxc.svelte-19itaxc{display:flex;flex-direction:column;gap:14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.pve-header.svelte-19itaxc.svelte-19itaxc{display:flex;align-items:center;gap:8px}.pve-title.svelte-19itaxc.svelte-19itaxc{font-size:14px;font-weight:600;color:#111827}.pve-badge.svelte-19itaxc.svelte-19itaxc{padding:2px 8px;background:#e0e7ff;color:#4338ca;border-radius:999px;font-size:11px;font-weight:700;letter-spacing:.02em}.pve-canvas.svelte-19itaxc.svelte-19itaxc{padding:10px 12px;border:1px solid #d1d5db;border-radius:8px;background:#fff;min-height:48px;line-height:2.1;word-break:break-all;cursor:text;-webkit-user-select:text;user-select:text}.pve-text-seg.svelte-19itaxc.svelte-19itaxc{white-space:pre-wrap;color:#374151;font-family:Menlo,Courier New,monospace;font-size:13px;border-radius:2px}.pve-text-seg--active.svelte-19itaxc.svelte-19itaxc{background:#fef9c3}.pve-chip.svelte-19itaxc.svelte-19itaxc{display:inline-flex;align-items:center;gap:3px;padding:2px 5px 2px 8px;margin:0 2px;border:1.5px solid;border-radius:999px;font-family:Menlo,Courier New,monospace;font-size:12px;vertical-align:middle;line-height:1.5}.pve-chip--text.svelte-19itaxc.svelte-19itaxc{border-color:#3b82f6;background:#eff6ff;color:#1d4ed8}.pve-chip--number.svelte-19itaxc.svelte-19itaxc{border-color:#10b981;background:#ecfdf5;color:#065f46}.pve-chip--decimal.svelte-19itaxc.svelte-19itaxc{border-color:#06b6d4;background:#ecfeff;color:#155e75}.pve-chip--date.svelte-19itaxc.svelte-19itaxc{border-color:#f59e0b;background:#fffbeb;color:#b45309}.pve-chip-label.svelte-19itaxc.svelte-19itaxc{font-weight:600}.pve-chip-remove.svelte-19itaxc.svelte-19itaxc{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:none;font-size:15px;cursor:pointer;border-radius:50%;line-height:1;transition:background .12s,color .12s}.pve-chip--text.svelte-19itaxc .pve-chip-remove.svelte-19itaxc{color:#60a5fa}.pve-chip--text.svelte-19itaxc .pve-chip-remove.svelte-19itaxc:hover{background:#bfdbfe;color:#1e3a8a}.pve-chip--number.svelte-19itaxc .pve-chip-remove.svelte-19itaxc{color:#34d399}.pve-chip--number.svelte-19itaxc .pve-chip-remove.svelte-19itaxc:hover{background:#a7f3d0;color:#064e3b}.pve-chip--decimal.svelte-19itaxc .pve-chip-remove.svelte-19itaxc{color:#22d3ee}.pve-chip--decimal.svelte-19itaxc .pve-chip-remove.svelte-19itaxc:hover{background:#a5f3fc;color:#164e63}.pve-chip--date.svelte-19itaxc .pve-chip-remove.svelte-19itaxc{color:#fbbf24}.pve-chip--date.svelte-19itaxc .pve-chip-remove.svelte-19itaxc:hover{background:#fde68a;color:#78350f}.pve-action-bar.svelte-19itaxc.svelte-19itaxc{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 12px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;flex-wrap:wrap}.pve-sel-preview.svelte-19itaxc.svelte-19itaxc{font-size:13px;color:#374151;min-width:0;flex:1}.pve-sel-code.svelte-19itaxc.svelte-19itaxc{background:#d1fae5;color:#065f46;padding:1px 5px;border-radius:4px;font-family:Menlo,Courier New,monospace;font-size:12px;max-width:220px;display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.pve-action-bar-btns.svelte-19itaxc.svelte-19itaxc{display:flex;gap:8px;flex-shrink:0}.pve-preview.svelte-19itaxc.svelte-19itaxc{display:flex;flex-direction:column;gap:4px}.pve-preview-label.svelte-19itaxc.svelte-19itaxc{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#9ca3af}.pve-preview-code.svelte-19itaxc.svelte-19itaxc{display:block;padding:8px 10px;background:#f3f4f6;border-radius:6px;font-family:Menlo,Courier New,monospace;font-size:12px;color:#374151;word-break:break-all;white-space:pre-wrap}.pve-footer.svelte-19itaxc.svelte-19itaxc{display:flex;justify-content:flex-end}.pve-btn.svelte-19itaxc.svelte-19itaxc{padding:7px 16px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:1px solid transparent;transition:background .12s}.pve-btn-primary.svelte-19itaxc.svelte-19itaxc{background:#4f46e5;color:#fff;border-color:#4f46e5}.pve-btn-primary.svelte-19itaxc.svelte-19itaxc:hover{background:#4338ca;border-color:#4338ca}.pve-btn-text.svelte-19itaxc.svelte-19itaxc{background:#3b82f6;color:#fff;border-color:#3b82f6}.pve-btn-text.svelte-19itaxc.svelte-19itaxc:hover{background:#2563eb;border-color:#2563eb}.pve-btn-number.svelte-19itaxc.svelte-19itaxc{background:#10b981;color:#fff;border-color:#10b981}.pve-btn-number.svelte-19itaxc.svelte-19itaxc:hover{background:#059669;border-color:#059669}.pve-btn-decimal.svelte-19itaxc.svelte-19itaxc{background:#06b6d4;color:#fff;border-color:#06b6d4}.pve-btn-decimal.svelte-19itaxc.svelte-19itaxc:hover{background:#0891b2;border-color:#0891b2}.pve-btn-date.svelte-19itaxc.svelte-19itaxc{background:#f59e0b;color:#fff;border-color:#f59e0b}.pve-btn-date.svelte-19itaxc.svelte-19itaxc:hover{background:#d97706;border-color:#d97706}.pve-btn-ghost.svelte-19itaxc.svelte-19itaxc{background:transparent;color:#6b7280;border-color:#d1d5db}.pve-btn-ghost.svelte-19itaxc.svelte-19itaxc:hover{background:#f9fafb}
|
package/dist/index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Loco — Translation Manager</title>
|
|
7
|
+
<script type="module" crossorigin src="/loco/dashboard/assets/index-CGo6e-bA.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/loco/dashboard/assets/index-DBcQDZ75.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import Fastify from 'fastify';
|
|
2
|
+
export declare function buildApp(project: any): Promise<Fastify.FastifyInstance<import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>, import("node:http").IncomingMessage, import("node:http").ServerResponse<import("node:http").IncomingMessage>, Fastify.FastifyBaseLogger, Fastify.FastifyTypeProviderDefault>>;
|
|
3
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../server/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAqB9B,wBAAsB,QAAQ,CAAC,OAAO,EAAE,GAAG,oUA0I1C"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import Fastify from 'fastify';
|
|
2
|
+
import cors from '@fastify/cors';
|
|
3
|
+
import fastifyStatic from '@fastify/static';
|
|
4
|
+
import fastifySwagger from '@fastify/swagger';
|
|
5
|
+
import fastifySwaggerUi from '@fastify/swagger-ui';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { PROJECT_ROOT, BASE_PATH } from './config.js';
|
|
9
|
+
// Route plugins
|
|
10
|
+
import projectRoutes from './routes/project.js';
|
|
11
|
+
import textnodesRoutes from './routes/textnodes.js';
|
|
12
|
+
import translationsRoutes from './routes/translations.js';
|
|
13
|
+
import languagesRoutes from './routes/languages.js';
|
|
14
|
+
import screenshotsRoutes from './routes/screenshots.js';
|
|
15
|
+
import exportRoutes from './routes/export.js';
|
|
16
|
+
import promptsRoutes from './routes/prompts.js';
|
|
17
|
+
import aiJobsRoutes from './routes/ai-jobs.js';
|
|
18
|
+
import chromeExtensionRoutes from './routes/chrome-extension.js';
|
|
19
|
+
import backupRoutes from './routes/backup.js';
|
|
20
|
+
export async function buildApp(project) {
|
|
21
|
+
const app = Fastify({
|
|
22
|
+
logger: false,
|
|
23
|
+
// Strip BASE_PATH prefix so Vite-built assets and relative API calls work
|
|
24
|
+
// behind a reverse proxy (e.g. /loco/api/... → /api/...).
|
|
25
|
+
rewriteUrl: BASE_PATH
|
|
26
|
+
? (req) => {
|
|
27
|
+
const url = req.url || '';
|
|
28
|
+
if (url.startsWith(BASE_PATH + '/'))
|
|
29
|
+
return url.slice(BASE_PATH.length);
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
32
|
+
: undefined,
|
|
33
|
+
});
|
|
34
|
+
// ── CORS
|
|
35
|
+
await app.register(cors, { origin: '*' });
|
|
36
|
+
// ── Swagger / OpenAPI
|
|
37
|
+
await app.register(fastifySwagger, {
|
|
38
|
+
openapi: {
|
|
39
|
+
openapi: '3.0.3',
|
|
40
|
+
info: {
|
|
41
|
+
title: 'Loco Translation API',
|
|
42
|
+
description: 'API for the Loco translation management system',
|
|
43
|
+
version: '1.0.0',
|
|
44
|
+
},
|
|
45
|
+
components: {
|
|
46
|
+
securitySchemes: {
|
|
47
|
+
ApiKeyAuth: {
|
|
48
|
+
type: 'apiKey',
|
|
49
|
+
in: 'header',
|
|
50
|
+
name: 'X-API-Key',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
security: [{ ApiKeyAuth: [] }],
|
|
55
|
+
tags: [
|
|
56
|
+
{ name: 'Project', description: 'Project management and health check' },
|
|
57
|
+
{ name: 'Text Nodes', description: 'Text node registration and management' },
|
|
58
|
+
{ name: 'Translations', description: 'Translation CRUD and CDN fetch' },
|
|
59
|
+
{ name: 'Languages', description: 'Available language listing' },
|
|
60
|
+
{ name: 'Screenshots', description: 'Page screenshot storage' },
|
|
61
|
+
{ name: 'Export', description: 'Translation export' },
|
|
62
|
+
{ name: 'Prompts', description: 'AI prompt template management' },
|
|
63
|
+
{ name: 'AI Jobs', description: 'Bulk AI translation jobs' },
|
|
64
|
+
{ name: 'Chrome Extension', description: 'Chrome extension sidepanel API' },
|
|
65
|
+
{ name: 'Backup', description: 'Database backup' },
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
await app.register(fastifySwaggerUi, {
|
|
70
|
+
routePrefix: '/api/docs',
|
|
71
|
+
...(BASE_PATH ? { indexPrefix: BASE_PATH } : {}),
|
|
72
|
+
uiConfig: {
|
|
73
|
+
docExpansion: 'list',
|
|
74
|
+
deepLinking: true,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
// ── Register route plugins
|
|
78
|
+
// routeOpts is shared across all route plugins and the auth hook.
|
|
79
|
+
// When project.ts regenerates the API key, it updates routeOpts.project,
|
|
80
|
+
// so the auth hook always reads the latest api_key.
|
|
81
|
+
const routeOpts = { project };
|
|
82
|
+
// ── API key auth for all /api/* routes
|
|
83
|
+
app.addHook('onRequest', (req, reply, done) => {
|
|
84
|
+
if (!req.url.startsWith('/api') && !req.url.startsWith('/api/'))
|
|
85
|
+
return done();
|
|
86
|
+
// Allow unauthenticated access to health check, project bootstrap, and Swagger docs
|
|
87
|
+
if (req.url === '/api' || req.url === '/api/' || req.url === '/api/project')
|
|
88
|
+
return done();
|
|
89
|
+
if (req.url.startsWith('/api/docs'))
|
|
90
|
+
return done();
|
|
91
|
+
const key = req.headers['x-api-key'];
|
|
92
|
+
if (!key || key !== routeOpts.project.api_key) {
|
|
93
|
+
reply.code(401).send({ error: 'Unauthorized — missing or invalid X-API-Key header' });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
done();
|
|
97
|
+
});
|
|
98
|
+
await app.register(projectRoutes, routeOpts);
|
|
99
|
+
await app.register(textnodesRoutes, routeOpts);
|
|
100
|
+
await app.register(translationsRoutes, routeOpts);
|
|
101
|
+
await app.register(languagesRoutes, routeOpts);
|
|
102
|
+
await app.register(screenshotsRoutes, routeOpts);
|
|
103
|
+
await app.register(exportRoutes, routeOpts);
|
|
104
|
+
await app.register(promptsRoutes, routeOpts);
|
|
105
|
+
await app.register(aiJobsRoutes, routeOpts);
|
|
106
|
+
await app.register(chromeExtensionRoutes, routeOpts);
|
|
107
|
+
await app.register(backupRoutes, routeOpts);
|
|
108
|
+
// ── Static: CDN (public/)
|
|
109
|
+
const publicDir = join(PROJECT_ROOT, 'public');
|
|
110
|
+
await app.register(fastifyStatic, {
|
|
111
|
+
root: publicDir,
|
|
112
|
+
prefix: '/cdn/',
|
|
113
|
+
decorateReply: false,
|
|
114
|
+
setHeaders: (res, path) => {
|
|
115
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
116
|
+
res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
|
|
117
|
+
if (path.endsWith('.js')) {
|
|
118
|
+
res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
|
|
119
|
+
}
|
|
120
|
+
else if (path.endsWith('.json')) {
|
|
121
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
// ── Static: Test pages (test-pages/ → /test-pages/)
|
|
126
|
+
const testPagesDir = join(PROJECT_ROOT, 'test-pages');
|
|
127
|
+
if (existsSync(testPagesDir)) {
|
|
128
|
+
await app.register(async function testPagesPlugin(scope) {
|
|
129
|
+
scope.register(fastifyStatic, {
|
|
130
|
+
root: testPagesDir,
|
|
131
|
+
prefix: '/test-pages/',
|
|
132
|
+
decorateReply: false,
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// ── Static: Dashboard (dist/) — production only
|
|
137
|
+
const distDir = join(PROJECT_ROOT, 'dist');
|
|
138
|
+
if (existsSync(distDir)) {
|
|
139
|
+
await app.register(fastifyStatic, {
|
|
140
|
+
root: distDir,
|
|
141
|
+
prefix: '/dashboard/',
|
|
142
|
+
decorateReply: false,
|
|
143
|
+
wildcard: true,
|
|
144
|
+
});
|
|
145
|
+
app.setNotFoundHandler((req, reply) => {
|
|
146
|
+
if (req.url.startsWith('/dashboard')) {
|
|
147
|
+
return reply.sendFile('index.html', distDir);
|
|
148
|
+
}
|
|
149
|
+
reply.code(404).send({ error: 'Not found' });
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return app;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../server/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const PROJECT_ROOT: string;
|
|
2
|
+
export declare const PORT: number;
|
|
3
|
+
export declare const BASE_PATH: string;
|
|
4
|
+
export declare const DATA_DIR: string;
|
|
5
|
+
export declare const AI_CONFIG: {
|
|
6
|
+
readonly HOSTNAME: "ai.bluehive.com";
|
|
7
|
+
readonly PORT: 443;
|
|
8
|
+
readonly PATH: "/api/v1/completion";
|
|
9
|
+
};
|
|
10
|
+
export declare const LIMITS: {
|
|
11
|
+
readonly MAX_URL_LENGTH: 2048;
|
|
12
|
+
readonly MAX_SCREENSHOT_SIZE: 500000;
|
|
13
|
+
readonly MAX_JOB_HISTORY: 50;
|
|
14
|
+
readonly API_KEY_LENGTH: 24;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../server/config.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY,QAAwB,CAAC;AAalD,eAAO,MAAM,IAAI,QAA2C,CAAC;AAC7D,eAAO,MAAM,SAAS,QAA8B,CAAC;AAUrD,eAAO,MAAM,QAAQ,QAA+C,CAAC;AAErE,eAAO,MAAM,SAAS;;;;CAIZ,CAAC;AAEX,eAAO,MAAM,MAAM;;;;;CAKT,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { join, dirname } from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { existsSync, readFileSync } from 'fs';
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = dirname(__filename);
|
|
6
|
+
// Project root is one level up from server/ (or dist-server/ when compiled).
|
|
7
|
+
// When installed as an npm package this resolves to the package root inside node_modules.
|
|
8
|
+
export const PROJECT_ROOT = join(__dirname, '..');
|
|
9
|
+
// Load .env file (from user's cwd, not package root)
|
|
10
|
+
const envPath = join(process.cwd(), '.env');
|
|
11
|
+
if (existsSync(envPath)) {
|
|
12
|
+
for (const line of readFileSync(envPath, 'utf8').split('\n')) {
|
|
13
|
+
const match = line.match(/^([^#=]+)=(.*)$/);
|
|
14
|
+
if (match && !process.env[match[1].trim()]) {
|
|
15
|
+
process.env[match[1].trim()] = match[2].trim();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export const PORT = parseInt(process.env.PORT || '6101', 10);
|
|
20
|
+
export const BASE_PATH = process.env.BASE_PATH || ''; // e.g. '/loco' for reverse-proxy deployments
|
|
21
|
+
// Data directory for the SQLite database and backups.
|
|
22
|
+
// When running from source (dev), use server/data/ inside the repo.
|
|
23
|
+
// When installed as an npm package, default to .loco/ in the user's cwd.
|
|
24
|
+
// Always overridable via LOCO_DATA_DIR env var.
|
|
25
|
+
const _isDevSource = existsSync(join(PROJECT_ROOT, 'server', 'index.ts'));
|
|
26
|
+
const _defaultDataDir = _isDevSource
|
|
27
|
+
? join(PROJECT_ROOT, 'server', 'data')
|
|
28
|
+
: join(process.cwd(), '.loco');
|
|
29
|
+
export const DATA_DIR = process.env.LOCO_DATA_DIR || _defaultDataDir;
|
|
30
|
+
export const AI_CONFIG = {
|
|
31
|
+
HOSTNAME: 'ai.bluehive.com',
|
|
32
|
+
PORT: 443,
|
|
33
|
+
PATH: '/api/v1/completion',
|
|
34
|
+
};
|
|
35
|
+
export const LIMITS = {
|
|
36
|
+
MAX_URL_LENGTH: 2048,
|
|
37
|
+
MAX_SCREENSHOT_SIZE: 500000,
|
|
38
|
+
MAX_JOB_HISTORY: 50,
|
|
39
|
+
API_KEY_LENGTH: 24,
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../server/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAE9C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,6EAA6E;AAC7E,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAElD,qDAAqD;AACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;AAC5C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC5C,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,6CAA6C;AAEnG,sDAAsD;AACtD,oEAAoE;AACpE,yEAAyE;AACzE,gDAAgD;AAChD,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAC1E,MAAM,eAAe,GAAG,YAAY;IAClC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC;IACtC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,eAAe,CAAC;AAErE,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,QAAQ,EAAE,iBAAiB;IAC3B,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,oBAAoB;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,cAAc,EAAE,IAAI;IACpB,mBAAmB,EAAE,MAAM;IAC3B,eAAe,EAAE,EAAE;IACnB,cAAc,EAAE,EAAE;CACV,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import Database, { type Database as DatabaseType } from 'better-sqlite3';
|
|
2
|
+
import * as schema from './schema.js';
|
|
3
|
+
export declare const db: import("drizzle-orm/better-sqlite3").BetterSQLite3Database<typeof schema> & {
|
|
4
|
+
$client: Database.Database;
|
|
5
|
+
};
|
|
6
|
+
export declare const rawDb: DatabaseType;
|
|
7
|
+
export { schema };
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../server/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,KAAK,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIzE,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAuBtC,eAAO,MAAM,EAAE;;CAA8B,CAAC;AAC9C,eAAO,MAAM,KAAK,EAAE,YAAqB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { existsSync, copyFileSync, mkdirSync } from 'fs';
|
|
5
|
+
import * as schema from './schema.js';
|
|
6
|
+
import { DATA_DIR } from '../config.js';
|
|
7
|
+
const dataDir = DATA_DIR;
|
|
8
|
+
const dbPath = join(dataDir, 'loco.db');
|
|
9
|
+
// Ensure data directory exists
|
|
10
|
+
mkdirSync(dataDir, { recursive: true });
|
|
11
|
+
// Auto-migrate: if loco.db exists in cwd (old location) but not yet in the new data dir
|
|
12
|
+
const oldDbPath = join(process.cwd(), 'loco.db');
|
|
13
|
+
if (!existsSync(dbPath) && existsSync(oldDbPath)) {
|
|
14
|
+
console.log(`[db] Migrating database from ${oldDbPath} to ${dbPath}`);
|
|
15
|
+
copyFileSync(oldDbPath, dbPath);
|
|
16
|
+
// Also copy WAL and SHM files if they exist
|
|
17
|
+
if (existsSync(oldDbPath + '-wal'))
|
|
18
|
+
copyFileSync(oldDbPath + '-wal', dbPath + '-wal');
|
|
19
|
+
if (existsSync(oldDbPath + '-shm'))
|
|
20
|
+
copyFileSync(oldDbPath + '-shm', dbPath + '-shm');
|
|
21
|
+
console.log(`[db] Migration complete. You can safely delete the old ${oldDbPath}`);
|
|
22
|
+
}
|
|
23
|
+
const sqlite = new Database(dbPath);
|
|
24
|
+
sqlite.pragma('journal_mode = WAL');
|
|
25
|
+
export const db = drizzle(sqlite, { schema });
|
|
26
|
+
export const rawDb = sqlite;
|
|
27
|
+
export { schema };
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAA2C,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,OAAO,GAAG,QAAQ,CAAC;AACzB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAExC,+BAA+B;AAC/B,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAExC,wFAAwF;AACxF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;AACjD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,gCAAgC,SAAS,OAAO,MAAM,EAAE,CAAC,CAAC;IACtE,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAChC,4CAA4C;IAC5C,IAAI,UAAU,CAAC,SAAS,GAAG,MAAM,CAAC;QAAE,YAAY,CAAC,SAAS,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACtF,IAAI,UAAU,CAAC,SAAS,GAAG,MAAM,CAAC;QAAE,YAAY,CAAC,SAAS,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,CAAC,0DAA0D,SAAS,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAEpC,MAAM,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,KAAK,GAAiB,MAAM,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,CAAC"}
|