github-issue-tower-defence-management 1.142.1 → 1.142.3
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/.github/workflows/test.yml +1 -0
- package/.github/workflows/umino-project.yml +2 -8
- package/CHANGELOG.md +14 -0
- package/README.md +2 -2
- package/bin/adapter/entry-points/console/ui-dist/assets/index-2c5E3tdu.js +81 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/index-BaGbcbYI.css +2 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/bin/adapter/repositories/GoogleSpreadsheetRepository.js +10 -2
- package/bin/adapter/repositories/GoogleSpreadsheetRepository.js.map +1 -1
- package/bin/domain/usecases/OauthTokenSelectUseCase.js +2 -2
- package/bin/domain/usecases/OauthTokenSelectUseCase.js.map +1 -1
- package/package.json +39 -39
- package/src/adapter/entry-points/console/ui/vite.config.ts +1 -1
- package/src/adapter/entry-points/console/ui-dist/assets/index-2c5E3tdu.js +81 -0
- package/src/adapter/entry-points/console/ui-dist/assets/index-BaGbcbYI.css +2 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.test.ts +2 -2
- package/src/adapter/repositories/GoogleSpreadsheetRepository.integration.test.ts +189 -55
- package/src/adapter/repositories/GoogleSpreadsheetRepository.test.ts +63 -5
- package/src/adapter/repositories/GoogleSpreadsheetRepository.ts +17 -2
- package/src/adapter/repositories/LocalStorageRepository.integration.test.ts +1 -1
- package/src/domain/usecases/OauthTokenSelectUseCase.test.ts +33 -11
- package/src/domain/usecases/OauthTokenSelectUseCase.ts +2 -2
- package/types/adapter/repositories/GoogleSpreadsheetRepository.d.ts +1 -0
- package/types/adapter/repositories/GoogleSpreadsheetRepository.d.ts.map +1 -1
- package/types/domain/usecases/OauthTokenSelectUseCase.d.ts +2 -2
- package/types/domain/usecases/OauthTokenSelectUseCase.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-BTtIpfv_.css +0 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-CMK3yyfo.js +0 -103
- package/src/adapter/entry-points/console/ui-dist/assets/index-BTtIpfv_.css +0 -1
- package/src/adapter/entry-points/console/ui-dist/assets/index-CMK3yyfo.js +0 -103
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@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-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--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}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, 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;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--radius-md:.375rem;--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);--color-input:#e5e5e5;--color-ring:#0a0a0a;--color-background:#fff;--color-foreground:#0a0a0a;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary:#f5f5f5;--color-secondary-foreground:#171717;--color-accent:#f5f5f5;--color-accent-foreground:#171717}}@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%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, 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;-webkit-text-decoration:inherit;-webkit-text-decoration: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:where(:not(iframe)){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]){appearance:button}::file-selector-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{.visible{visibility:visible}.relative{position:relative}.static{position:static}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.block{display:block}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-input{border-color:var(--color-input)}.border-transparent{border-color:#0000}.bg-background{background-color:var(--color-background)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.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-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.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)}.whitespace-nowrap{white-space:nowrap}.text-foreground{color:var(--color-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.lowercase{text-transform:lowercase}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.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))}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--color-accent)}.hover\:bg-primary\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:#f5f5f5cc}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--color-secondary) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--color-accent-foreground)}}.focus-visible\:ring-2:focus-visible{--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-visible\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}}html{font-size:clamp(15px,2.1vw,26px)}body{color:#e6edf3;background-color:#0d1117;margin:0;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}.console-app{flex-direction:column;width:100%;min-height:100dvh;display:flex}.console-tabbar{-webkit-overflow-scrolling:touch;background:#161b22;border-bottom:2px solid #30363d;flex-wrap:nowrap;align-items:stretch;gap:0;min-height:42px;padding:0 8px;display:flex;overflow-x:auto}.console-tab{color:#8b949e;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;margin-bottom:-2px;padding:10px 14px;font-size:.8125rem;font-weight:500;line-height:1.2;text-decoration:none;display:inline-flex}.console-tab:hover{color:#e6edf3}.console-tab[data-active=true]{color:#e6edf3;border-bottom-color:#2f81f7;font-weight:700}.console-tab-badge{text-align:center;color:#e6edf3;background:#484f58;border-radius:20px;min-width:20px;padding:1px 7px;font-size:.6875rem;font-weight:700;line-height:1.5}.console-tab-badge[data-zero=true]{color:#8b949e;background:#30363d}.console-tab-pjname{color:#8b949e;align-self:center;margin-left:auto;padding:0 8px;font-size:.7188rem}.console-tab-geninfo{color:#8b949e;align-self:center;padding:0 4px;font-size:.6875rem}.console-list{margin:0;padding:12px 18px 18px;list-style:none}.console-list-group{list-style:none}.console-item-row .console-item-icon{flex:none;margin-top:3px}.console-group-header{background:#0b0f14;border-bottom:1px solid #21262d;justify-content:space-between;align-items:center;padding:6px 12px;display:flex}.console-storytag{align-items:center;gap:8px;font-size:.8125rem;font-weight:700;display:inline-flex}.console-story-dot{border-radius:999px;width:10px;height:10px;display:inline-block}.console-group-count{color:#8b949e;font-size:.75rem}.console-item-row{color:#e6edf3;text-align:left;cursor:pointer;background:#161b22;border:1px solid #30363d;border-radius:8px;align-items:flex-start;gap:14px;width:100%;margin-bottom:10px;padding:12px 16px;display:flex}.console-item-row:hover{background:#1a2029;border-color:#484f58}.console-item-row[data-active=true]{background:#1a2029;border-color:#4493f8}.console-item-meta{flex:1;min-width:0}.console-item-title{font-size:.9063rem;font-weight:600;display:block}.console-item-sub{color:#8b949e;margin-top:3px;font-size:.7813rem;display:block}.console-item-pill{color:#8b949e;border:1px solid #30363d;border-radius:20px;margin-right:6px;padding:1px 8px;font-size:.6875rem;display:inline-block}.console-item-createdat{color:#8b949e;cursor:help}.console-item-fields{color:#adbac7;flex-wrap:wrap;gap:4px 10px;margin-top:4px;font-size:.7188rem;display:flex}.console-item-field{word-break:break-all;align-items:baseline;gap:4px;min-width:0;display:inline-flex}.console-item-field-label{color:#6e7681;text-transform:uppercase;letter-spacing:.03em;font-size:.625rem}.console-list-message{color:#8b949e;padding:16px;font-size:.875rem}.console-list-empty{text-align:center;color:#8b949e;padding:40px;font-size:.875rem}.console-list-error,.console-comment-error,.console-files-error,.console-commits-error,.console-detail-body-error{color:#f85149}.console-detail{flex-direction:column;flex:1 0 auto;gap:12px;padding:16px 16px 0;display:flex}.console-detail-title{align-items:center;gap:8px;margin:0;font-size:1.25rem;display:flex}.console-detail-title-text{flex:1}.console-detail-number{color:#8b949e;font-weight:400}.console-detail-closed-label{color:#a371f7;font-size:.8125rem}.console-detail-subbar{align-items:center;gap:12px;font-size:.8125rem;display:flex}.console-detail-link{color:#4493f8}.console-detail-repo{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-copy-url-button{color:#c9d1d9;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-url-button:hover{color:#e6edf3;background-color:#21262d}.console-detail-pill,.console-label-chip,.console-detail-status-chip{border:1px solid #30363d;border-radius:999px;padding:2px 8px;font-size:.75rem;display:inline-block}.console-detail-pr-status-row{flex-wrap:wrap;align-items:center;gap:6px;margin-top:-4px;display:flex}.console-detail-pr-status{flex-wrap:wrap;align-items:center;gap:6px;display:inline-flex}.console-detail-ci-missing{opacity:.85;font-weight:400}.console-detail-mergeable-chip{font-weight:600}.console-detail-mergeable-chip-unknown{opacity:.7;font-weight:400}.console-detail-labels{flex-wrap:wrap;gap:6px;display:flex}.console-detail-createdat{color:#8b949e;font-size:.75rem}.console-panel{border:1px solid #30363d;border-radius:8px;overflow:hidden}.console-panel-header{background:#161b22;justify-content:space-between;align-items:center;display:flex}.console-panel-toggle{color:#e6edf3;text-align:left;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;gap:8px;padding:6px 12px;font-size:.875rem;font-weight:600;display:flex}.console-panel-toggle:hover{background:#1a2029}.console-panel-action{padding:6px 12px}.console-panel-body{padding:12px}.console-markdown{word-break:break-word;font-size:.875rem;line-height:1.5}.console-markdown ul{margin:.5em 0;padding-left:1.5em;list-style:outside}.console-markdown ol{margin:.5em 0;padding-left:1.5em;list-style:decimal}.console-markdown li{margin:.25em 0}.console-markdown table{border-collapse:collapse;margin:.5em 0}.console-markdown th,.console-markdown td{border:1px solid #30363d;padding:4px 8px}.console-markdown th{background:#161b22}.console-markdown h1,.console-markdown h2,.console-markdown h3,.console-markdown h4,.console-markdown h5,.console-markdown h6{margin:1em 0 .5em;font-weight:700;line-height:1.25}.console-markdown h1{font-size:1.6em}.console-markdown h2{font-size:1.4em}.console-markdown h3{font-size:1.2em}.console-markdown h4{font-size:1.05em}.console-markdown h5{font-size:.95em}.console-markdown h6{color:#8b949e;font-size:.9em}.console-markdown pre{background:#161b22;border:1px solid #30363d;border-radius:6px;margin:.5em 0;padding:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8125rem;line-height:1.45;overflow-x:auto}.console-markdown code{background:#6e768166;border-radius:4px;padding:.15em .4em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em}.console-markdown pre code{font-size:inherit;background:0 0;border-radius:0;padding:0}.console-markdown blockquote{color:#8b949e;border-left:3px solid #30363d;margin:.5em 0;padding:0 1em}.console-markdown a{color:#4493f8;text-decoration:none}.console-markdown a:hover{text-decoration:underline}.console-markdown-reference-host{display:inline}.console-markdown-reference{vertical-align:baseline;align-items:center;gap:.25em;display:inline-flex}.console-markdown-reference .console-item-icon{flex-shrink:0}.console-markdown-reference-title{text-decoration:none}.console-markdown-reference:hover .console-markdown-reference-title{text-decoration:underline}.console-markdown hr{border:none;border-top:1px solid #30363d;margin:1em 0}.console-mermaid-error{color:#f85149;font-size:.8125rem}.console-comment{background:#161b22;border:1px solid #30363d;border-radius:8px;margin-bottom:10px;padding:12px 16px}.console-comment-header{color:#8b949e;gap:8px;font-size:.75rem;display:flex}.console-comment-show-all{color:#e6edf3;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;margin-bottom:10px;padding:6px 12px;font-size:.75rem;font-weight:600}.console-comment-show-all:hover{background-color:#262c34;border-color:#484f58}.console-comment-author{color:#e6edf3;font-weight:600}.console-files,.console-commits{margin:0;padding:0;list-style:none}.console-commit{align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file{flex-direction:column;font-size:.8125rem;display:flex}.console-file-tree,.console-file-tree-children{margin:0;padding:0;list-style:none}.console-file-tree-dir{flex-direction:column;display:flex}.console-file-tree-dir-name{color:#8b949e;align-items:center;gap:6px;padding:4px 0;font-weight:600;display:flex}.console-file-tree-dir-icon{flex:none}.console-file-badge{text-align:center;border:1px solid;border-radius:4px;width:18px;font-size:.6875rem}.console-file-path,.console-commit-message{flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-add,.console-pr-add{color:#3fb950}.console-file-del,.console-pr-del{color:#f85149}.console-commit-sha{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-actionbar{z-index:100;padding:10px 16px;padding-bottom:calc(10px + env(safe-area-inset-bottom));background:#161b22;border-top:2px solid #30363d;margin-top:auto;position:sticky;bottom:0}.console-operation-bar{flex-direction:column;gap:8px;width:100%;display:flex}.console-op-group{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.console-op-group-review{gap:10px}.console-op-group-stories{max-height:33vh;overflow-y:auto}.console-op-button{color:#e6edf3;white-space:nowrap;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:9px 16px;font-size:.8125rem;font-weight:600}.console-op-button:hover{border-color:#484f58}.console-op-button-approve{color:#fff;background:#238636;border-color:#2ea043}.console-op-button-reject{color:#ffd166;background:#7d5000;border-color:#a06800}.console-op-button-wrong{color:#f85149;background:#3a1518;border-color:#f85149}.console-op-button-unneeded{color:#aab0b8;background:#2a2d31;border-color:#6e7681}.console-op-button-snooze{color:#79c0ff;background:#1c2b4a;border-color:#4493f8}.console-pr-section{border:1px solid #30363d;border-radius:8px;flex-direction:column;gap:10px;padding:12px;display:flex}.console-pr-statbar{color:#8b949e;gap:12px;font-size:.75rem;display:flex}.console-detail-screen{flex-direction:column;flex:1 0 auto;display:flex}.console-panel-open-link{color:#4493f8;font-size:.8125rem;font-weight:400}.console-composer{margin-top:4px}.console-composer-toggle{color:#8b949e;cursor:pointer;background:0 0;border:none;padding:2px 0;font-size:.7813rem}.console-composer-toggle:hover{color:#e6edf3}.console-composer-posted{flex-direction:column;gap:8px;margin-top:8px;display:flex}.console-composer-form{margin-top:8px}.console-composer-input{box-sizing:border-box;color:#e6edf3;width:100%;font:inherit;resize:vertical;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:8px;font-size:.875rem}.console-composer-row{justify-content:flex-end;align-items:center;gap:8px;margin-top:6px;display:flex}.console-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #2ea043;border-radius:6px;padding:7px 16px;font-size:.8125rem;font-weight:600}.console-composer-submit:disabled{opacity:.6;cursor:default}.console-composer-status{color:#8b949e;font-size:.75rem}.console-composer-error{color:#f85149}.console-undo-toast{z-index:9998;white-space:nowrap;border-radius:10px;align-items:center;gap:12px;max-width:92vw;padding:12px 18px;font-size:.8438rem;display:flex;position:fixed;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 20px #0009}.console-undo-toast-green{color:#3fb950;background:#0d3320;border:1px solid #2ea043}.console-undo-toast-amber{color:#ffd166;background:#3a2800;border:1px solid #a06800}.console-undo-toast-red{color:#f85149;background:#3a1518;border:1px solid #da3633}.console-undo-toast-gray{color:#aab0b8;background:#2a2d31;border:1px solid #6e7681}.console-undo-toast-blue{color:#79c0ff;background:#0d1f40;border:1px solid #4493f8}.console-undo-toast-error{color:#f85149;background:#3a1518;border:1px solid #f85149}.console-undo-toast-message{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.console-undo-toast-undo{cursor:pointer;color:inherit;background:#ffffff1f;border:none;border-radius:6px;flex:none;padding:4px 12px;font-size:.8125rem;font-weight:700}.console-undo-toast-undo:hover{background:#ffffff38}.console-undo-toast-countdown{opacity:.7;flex:none;font-size:.6875rem}.console-undo-toast-bar{opacity:.5;background:currentColor;border-radius:0 0 10px 10px;height:3px;transition:width .1s linear;position:absolute;bottom:0;left:0}.console-file-row{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file-row:hover{background:#1a2029}.console-file-caret{color:#8b949e;flex:none;width:1em}.console-file-diff{border-collapse:collapse;width:100%;margin:4px 0 8px;font:.8125rem/1.6 ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-diff td{white-space:pre-wrap;word-break:break-word;vertical-align:top;padding:0 10px}.console-diff-ln{text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;white-space:nowrap;border-right:1px solid #30363d;width:1%;padding:0 8px}.console-file-diff td.console-diff-ln{white-space:nowrap;word-break:normal;overflow-wrap:normal}.console-diff-add td{background:#2ea04326}.console-diff-add .console-diff-code{color:#aff5b4}.console-diff-del td{background:#f8514926}.console-diff-del .console-diff-code{color:#ffdcd7}.console-diff-hunk td{color:#79c0ff;background:#161b22}.console-diff-ctx .console-diff-code{color:#c9d1d9}.console-file-diff-empty{color:#8b949e;padding:8px 14px;font-size:.75rem}.console-diff-comment-cell{text-align:center;-webkit-user-select:none;user-select:none;width:1%;padding:0 2px}.console-diff-comment-button{color:#6e7681;cursor:pointer;opacity:.6;background:0 0;border:1px solid #30363d;border-radius:4px;width:18px;height:18px;padding:0;font-size:.875rem;line-height:16px}.console-diff-row:hover .console-diff-comment-button,.console-diff-comment-button:focus-visible,.console-diff-comment-button[aria-expanded=true]{opacity:1;color:#fff;background:#1f6feb;border-color:#2f81f7}.console-diff-composer-row td{background:#0d1117;padding:6px 10px}.console-diff-composer{background:#161b22;border:1px solid #30363d;border-radius:6px;flex-direction:column;gap:6px;padding:8px;display:flex}.console-diff-composer-anchor{color:#8b949e;font-size:.6875rem}.console-diff-composer-input{resize:vertical;color:#c9d1d9;width:100%;font:inherit;background:#0d1117;border:1px solid #30363d;border-radius:6px;padding:6px 8px}.console-diff-composer-controls{align-items:center;gap:8px;display:flex}.console-diff-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #238636;border-radius:6px;padding:4px 12px}.console-diff-composer-submit:disabled{opacity:.6;cursor:default}.console-diff-composer-cancel{color:#c9d1d9;cursor:pointer;background:0 0;border:1px solid #30363d;border-radius:6px;padding:4px 12px}.console-diff-composer-status{color:#8b949e;font-size:.75rem}.console-diff-composer-error{color:#ff7b72}.console-diff-composer-posted{color:#3fb950;margin:0;font-size:.75rem}.console-pr-header{flex-wrap:wrap;align-items:center;gap:10px;padding-top:4px;display:flex}.console-pr-section-title{color:#e6edf3;font-size:.9375rem;font-weight:600}.console-pr-section-state{color:#8b949e;border:1px solid #6e7681;border-radius:999px;padding:1px 8px;font-size:.6875rem}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@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}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>TDPM Console</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-2c5E3tdu.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BaGbcbYI.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
|
@@ -308,8 +308,8 @@ describe('LiveSessionOauthTokenSelectHandler', () => {
|
|
|
308
308
|
expect(output.selectedName).toBeNull();
|
|
309
309
|
const diagnostics = output.diagnostics.join('\n');
|
|
310
310
|
expect(diagnostics).toContain('No eligible token');
|
|
311
|
-
expect(diagnostics).toContain('5h >=
|
|
312
|
-
expect(diagnostics).toContain('7d >=
|
|
311
|
+
expect(diagnostics).toContain('5h >= 25% free');
|
|
312
|
+
expect(diagnostics).toContain('7d >= 3% free');
|
|
313
313
|
expect(diagnostics).not.toContain('fake-busy');
|
|
314
314
|
});
|
|
315
315
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import dotenv from 'dotenv';
|
|
2
|
+
import { google } from 'googleapis';
|
|
2
3
|
import { GoogleSpreadsheetRepository } from './GoogleSpreadsheetRepository';
|
|
3
4
|
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
4
5
|
|
|
@@ -6,6 +7,24 @@ dotenv.config();
|
|
|
6
7
|
|
|
7
8
|
const GOOGLE_SERVICE_ACCOUNT_KEY = process.env.GOOGLE_SERVICE_ACCOUNT_KEY;
|
|
8
9
|
|
|
10
|
+
const integrationTestIsRequired =
|
|
11
|
+
process.env.GOOGLE_SHEETS_INTEGRATION_REQUIRED === 'true';
|
|
12
|
+
|
|
13
|
+
const credentialIsMissingWhileRequired =
|
|
14
|
+
integrationTestIsRequired && !GOOGLE_SERVICE_ACCOUNT_KEY;
|
|
15
|
+
|
|
16
|
+
describe('GoogleSpreadsheetRepository integration test credential', () => {
|
|
17
|
+
test('is available whenever these integration tests are required to run', () => {
|
|
18
|
+
expect(
|
|
19
|
+
credentialIsMissingWhileRequired
|
|
20
|
+
? 'GOOGLE_SERVICE_ACCOUNT_KEY is absent while GOOGLE_SHEETS_INTEGRATION_REQUIRED is true, so the Google Sheets integration tests would silently skip and prove nothing'
|
|
21
|
+
: 'the Google Sheets integration tests either hold their credential or are not required in this context',
|
|
22
|
+
).toBe(
|
|
23
|
+
'the Google Sheets integration tests either hold their credential or are not required in this context',
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
9
28
|
const describeWhenCredentials = GOOGLE_SERVICE_ACCOUNT_KEY
|
|
10
29
|
? describe
|
|
11
30
|
: describe.skip;
|
|
@@ -15,17 +34,101 @@ describeWhenCredentials('GoogleSpreadsheetRepository integration tests', () => {
|
|
|
15
34
|
jest.retryTimes(3, { logErrorsBeforeRetry: true });
|
|
16
35
|
|
|
17
36
|
const localStorageRepository = new LocalStorageRepository();
|
|
18
|
-
const
|
|
19
|
-
|
|
37
|
+
const spreadsheetId = '1N_3y0y46v5tHbra5YSm6PldflcsF1bkfeWDdQ3MRuXM';
|
|
38
|
+
const spreadsheetUrl = `https://docs.google.com/spreadsheets/d/${spreadsheetId}/edit?gid=0#gid=0`;
|
|
20
39
|
const repository = new GoogleSpreadsheetRepository(
|
|
21
40
|
localStorageRepository,
|
|
22
41
|
GOOGLE_SERVICE_ACCOUNT_KEY,
|
|
23
42
|
);
|
|
24
43
|
|
|
44
|
+
const scratchSheetNamePrefix = 'IntegrationScratch_';
|
|
45
|
+
const scratchSheetName = `${scratchSheetNamePrefix}${Date.now()}_${process.pid}`;
|
|
46
|
+
const abandonedScratchSheetAgeMilliseconds = 2 * 60 * 60 * 1000;
|
|
47
|
+
const rawSheetsClientKeyFile =
|
|
48
|
+
'./tmp/integration-test-service-account-key.json';
|
|
49
|
+
|
|
50
|
+
const createRawSheetsClient = () => {
|
|
51
|
+
if (!GOOGLE_SERVICE_ACCOUNT_KEY) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
'GOOGLE_SERVICE_ACCOUNT_KEY is required to run the Google Sheets integration tests',
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
localStorageRepository.write(
|
|
57
|
+
rawSheetsClientKeyFile,
|
|
58
|
+
GOOGLE_SERVICE_ACCOUNT_KEY,
|
|
59
|
+
);
|
|
60
|
+
const auth = new google.auth.GoogleAuth({
|
|
61
|
+
keyFile: rawSheetsClientKeyFile,
|
|
62
|
+
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
|
|
63
|
+
});
|
|
64
|
+
return google.sheets({ version: 'v4', auth });
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const listSheetTitles = async (): Promise<string[]> => {
|
|
68
|
+
const response = await createRawSheetsClient().spreadsheets.get({
|
|
69
|
+
spreadsheetId,
|
|
70
|
+
});
|
|
71
|
+
return (response.data.sheets ?? [])
|
|
72
|
+
.map((sheet) => sheet.properties?.title)
|
|
73
|
+
.filter((title): title is string => typeof title === 'string');
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const deleteSheetsByTitle = async (titles: string[]): Promise<void> => {
|
|
77
|
+
if (titles.length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const sheetsClient = createRawSheetsClient();
|
|
81
|
+
const response = await sheetsClient.spreadsheets.get({ spreadsheetId });
|
|
82
|
+
const sheetIds = (response.data.sheets ?? [])
|
|
83
|
+
.filter((sheet) => {
|
|
84
|
+
const title = sheet.properties?.title;
|
|
85
|
+
return typeof title === 'string' && titles.includes(title);
|
|
86
|
+
})
|
|
87
|
+
.map((sheet) => sheet.properties?.sheetId)
|
|
88
|
+
.filter((sheetId): sheetId is number => typeof sheetId === 'number');
|
|
89
|
+
if (sheetIds.length === 0) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
await sheetsClient.spreadsheets.batchUpdate({
|
|
93
|
+
spreadsheetId,
|
|
94
|
+
requestBody: {
|
|
95
|
+
requests: sheetIds.map((sheetId) => ({ deleteSheet: { sheetId } })),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const findAbandonedScratchSheetTitles = async (): Promise<string[]> => {
|
|
101
|
+
const titles = await listSheetTitles();
|
|
102
|
+
return titles
|
|
103
|
+
.filter((title) => title.startsWith(scratchSheetNamePrefix))
|
|
104
|
+
.filter((title) => title !== scratchSheetName)
|
|
105
|
+
.filter((title) => {
|
|
106
|
+
const createdAtMilliseconds = Number(
|
|
107
|
+
title.slice(scratchSheetNamePrefix.length).split('_')[0],
|
|
108
|
+
);
|
|
109
|
+
return (
|
|
110
|
+
Number.isFinite(createdAtMilliseconds) &&
|
|
111
|
+
Date.now() - createdAtMilliseconds >
|
|
112
|
+
abandonedScratchSheetAgeMilliseconds
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
25
117
|
beforeEach(async () => {
|
|
26
118
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
27
119
|
});
|
|
28
120
|
|
|
121
|
+
afterAll(async () => {
|
|
122
|
+
const abandonedTitles = await findAbandonedScratchSheetTitles();
|
|
123
|
+
await deleteSheetsByTitle([scratchSheetName, ...abandonedTitles]);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('getSpreadsheetId', () => {
|
|
127
|
+
test('extracts the spreadsheet id from the spreadsheet url', () => {
|
|
128
|
+
expect(repository.getSpreadsheetId(spreadsheetUrl)).toBe(spreadsheetId);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
29
132
|
describe('getSheet', () => {
|
|
30
133
|
const testCases: [string, string[][] | null][] = [
|
|
31
134
|
['SheetUndefined', null],
|
|
@@ -56,65 +159,96 @@ describeWhenCredentials('GoogleSpreadsheetRepository integration tests', () => {
|
|
|
56
159
|
});
|
|
57
160
|
});
|
|
58
161
|
|
|
59
|
-
describe('
|
|
60
|
-
|
|
61
|
-
[
|
|
62
|
-
|
|
63
|
-
['Sheet1', 1, 1, '123'],
|
|
64
|
-
['Sheet1', 2, 2, 'Test'],
|
|
65
|
-
];
|
|
162
|
+
describe('createNewSheetIfNotExists', () => {
|
|
163
|
+
test('creates the sheet and stays idempotent on a second call', async () => {
|
|
164
|
+
await deleteSheetsByTitle([scratchSheetName]);
|
|
165
|
+
expect(await listSheetTitles()).not.toContain(scratchSheetName);
|
|
66
166
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
167
|
+
await repository.createNewSheetIfNotExists(
|
|
168
|
+
spreadsheetUrl,
|
|
169
|
+
scratchSheetName,
|
|
170
|
+
);
|
|
171
|
+
expect(await listSheetTitles()).toContain(scratchSheetName);
|
|
172
|
+
expect(
|
|
173
|
+
await repository.getSheet(spreadsheetUrl, scratchSheetName),
|
|
174
|
+
).toBeNull();
|
|
175
|
+
|
|
176
|
+
await repository.createNewSheetIfNotExists(
|
|
177
|
+
spreadsheetUrl,
|
|
178
|
+
scratchSheetName,
|
|
179
|
+
);
|
|
180
|
+
const titlesAfterSecondCall = await listSheetTitles();
|
|
181
|
+
expect(
|
|
182
|
+
titlesAfterSecondCall.filter((title) => title === scratchSheetName)
|
|
183
|
+
.length,
|
|
184
|
+
).toBe(1);
|
|
185
|
+
});
|
|
78
186
|
});
|
|
79
187
|
|
|
80
188
|
describe('appendSheetValues', () => {
|
|
81
|
-
|
|
82
|
-
[
|
|
83
|
-
|
|
84
|
-
[
|
|
85
|
-
[
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
]
|
|
90
|
-
|
|
189
|
+
test('appends rows to a sheet it creates and keeps the earlier rows', async () => {
|
|
190
|
+
await deleteSheetsByTitle([scratchSheetName]);
|
|
191
|
+
|
|
192
|
+
await repository.appendSheetValues(spreadsheetUrl, scratchSheetName, [
|
|
193
|
+
['firstRowFirstColumn', 'firstRowSecondColumn'],
|
|
194
|
+
]);
|
|
195
|
+
expect(
|
|
196
|
+
await repository.getSheet(spreadsheetUrl, scratchSheetName),
|
|
197
|
+
).toEqual([['firstRowFirstColumn', 'firstRowSecondColumn']]);
|
|
198
|
+
|
|
199
|
+
await repository.appendSheetValues(spreadsheetUrl, scratchSheetName, [
|
|
200
|
+
['secondRowFirstColumn', 'secondRowSecondColumn'],
|
|
201
|
+
['thirdRowFirstColumn', 'thirdRowSecondColumn'],
|
|
202
|
+
]);
|
|
203
|
+
expect(
|
|
204
|
+
await repository.getSheet(spreadsheetUrl, scratchSheetName),
|
|
205
|
+
).toEqual([
|
|
206
|
+
['firstRowFirstColumn', 'firstRowSecondColumn'],
|
|
207
|
+
['secondRowFirstColumn', 'secondRowSecondColumn'],
|
|
208
|
+
['thirdRowFirstColumn', 'thirdRowSecondColumn'],
|
|
209
|
+
]);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
91
212
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const sheetName = 'AppendTest';
|
|
96
|
-
const initialSheet = await repository.getSheet(
|
|
97
|
-
spreadsheetUrl,
|
|
98
|
-
sheetName,
|
|
99
|
-
);
|
|
100
|
-
const initialLength = initialSheet ? initialSheet.length : 0;
|
|
213
|
+
describe('updateCell', () => {
|
|
214
|
+
test('creates the sheet when missing, writes a cell, and overwrites it', async () => {
|
|
215
|
+
await deleteSheetsByTitle([scratchSheetName]);
|
|
101
216
|
|
|
102
|
-
|
|
217
|
+
await repository.updateCell(
|
|
218
|
+
spreadsheetUrl,
|
|
219
|
+
scratchSheetName,
|
|
220
|
+
0,
|
|
221
|
+
0,
|
|
222
|
+
'firstValue',
|
|
223
|
+
);
|
|
224
|
+
expect(
|
|
225
|
+
await repository.getSheet(spreadsheetUrl, scratchSheetName),
|
|
226
|
+
).toEqual([['firstValue']]);
|
|
103
227
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
228
|
+
await repository.updateCell(
|
|
229
|
+
spreadsheetUrl,
|
|
230
|
+
scratchSheetName,
|
|
231
|
+
0,
|
|
232
|
+
0,
|
|
233
|
+
'updatedValue',
|
|
234
|
+
);
|
|
235
|
+
expect(
|
|
236
|
+
await repository.getSheet(spreadsheetUrl, scratchSheetName),
|
|
237
|
+
).toEqual([['updatedValue']]);
|
|
238
|
+
|
|
239
|
+
await repository.updateCell(
|
|
240
|
+
spreadsheetUrl,
|
|
241
|
+
scratchSheetName,
|
|
242
|
+
2,
|
|
243
|
+
2,
|
|
244
|
+
'thirdRowThirdColumn',
|
|
245
|
+
);
|
|
246
|
+
const sheet = await repository.getSheet(spreadsheetUrl, scratchSheetName);
|
|
247
|
+
if (!sheet) {
|
|
248
|
+
throw new Error('Sheet not found');
|
|
249
|
+
}
|
|
250
|
+
expect(sheet[0][0]).toBe('updatedValue');
|
|
251
|
+
expect(sheet[2][2]).toBe('thirdRowThirdColumn');
|
|
252
|
+
});
|
|
119
253
|
});
|
|
120
254
|
});
|
|
@@ -23,11 +23,43 @@ describe('GoogleSpreadsheetRepository', () => {
|
|
|
23
23
|
const spreadsheetUrl =
|
|
24
24
|
'https://docs.google.com/spreadsheets/d/1N_3y0y46v5tHbra5YSm6PldflcsF1bkfeWDdQ3MRuXM/edit?gid=0#gid=0';
|
|
25
25
|
|
|
26
|
-
const mockSpreadsheetsGet =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
26
|
+
const mockSpreadsheetsGet =
|
|
27
|
+
jest.fn<
|
|
28
|
+
(params: { spreadsheetId: string }) => Promise<SpreadsheetGetResponse>
|
|
29
|
+
>();
|
|
30
|
+
const mockSpreadsheetsValuesGet =
|
|
31
|
+
jest.fn<
|
|
32
|
+
(params: {
|
|
33
|
+
spreadsheetId: string;
|
|
34
|
+
range: string;
|
|
35
|
+
}) => Promise<ValuesGetResponse>
|
|
36
|
+
>();
|
|
37
|
+
const mockSpreadsheetsValuesUpdate =
|
|
38
|
+
jest.fn<
|
|
39
|
+
(params: {
|
|
40
|
+
spreadsheetId: string;
|
|
41
|
+
range: string;
|
|
42
|
+
valueInputOption: string;
|
|
43
|
+
requestBody: { values: string[][] };
|
|
44
|
+
}) => Promise<SimpleResponse>
|
|
45
|
+
>();
|
|
46
|
+
const mockSpreadsheetsValuesAppend =
|
|
47
|
+
jest.fn<
|
|
48
|
+
(params: {
|
|
49
|
+
spreadsheetId: string;
|
|
50
|
+
range: string;
|
|
51
|
+
valueInputOption: string;
|
|
52
|
+
requestBody: { values: string[][] };
|
|
53
|
+
}) => Promise<SimpleResponse>
|
|
54
|
+
>();
|
|
55
|
+
const mockSpreadsheetsBatchUpdate = jest.fn<
|
|
56
|
+
(params: {
|
|
57
|
+
spreadsheetId: string;
|
|
58
|
+
requestBody: {
|
|
59
|
+
requests: Array<{ addSheet?: { properties?: { title?: string } } }>;
|
|
60
|
+
};
|
|
61
|
+
}) => Promise<SimpleResponse>
|
|
62
|
+
>();
|
|
31
63
|
|
|
32
64
|
const mockSheetsClient = {
|
|
33
65
|
spreadsheets: {
|
|
@@ -289,6 +321,32 @@ describe('GoogleSpreadsheetRepository', () => {
|
|
|
289
321
|
);
|
|
290
322
|
});
|
|
291
323
|
|
|
324
|
+
test('does not recreate an existing sheet that holds no values', async () => {
|
|
325
|
+
mockSpreadsheetsGet.mockResolvedValue({
|
|
326
|
+
status: 200,
|
|
327
|
+
data: { sheets: [{ properties: { title: 'EmptyExistingSheet' } }] },
|
|
328
|
+
});
|
|
329
|
+
mockSpreadsheetsValuesGet.mockResolvedValue({
|
|
330
|
+
status: 200,
|
|
331
|
+
data: {},
|
|
332
|
+
});
|
|
333
|
+
mockSpreadsheetsValuesAppend.mockResolvedValue({
|
|
334
|
+
status: 200,
|
|
335
|
+
data: {},
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
await repository.appendSheetValues(spreadsheetUrl, 'EmptyExistingSheet', [
|
|
339
|
+
['Row'],
|
|
340
|
+
]);
|
|
341
|
+
|
|
342
|
+
expect(mockSpreadsheetsBatchUpdate).not.toHaveBeenCalled();
|
|
343
|
+
expect(mockSpreadsheetsValuesAppend).toHaveBeenCalledWith(
|
|
344
|
+
expect.objectContaining({
|
|
345
|
+
range: 'EmptyExistingSheet!A1:A',
|
|
346
|
+
}),
|
|
347
|
+
);
|
|
348
|
+
});
|
|
349
|
+
|
|
292
350
|
test('creates new sheet via batchUpdate when sheet does not exist', async () => {
|
|
293
351
|
mockSpreadsheetsGet.mockResolvedValue({
|
|
294
352
|
status: 200,
|
|
@@ -155,14 +155,29 @@ export class GoogleSpreadsheetRepository implements SpreadsheetRepository {
|
|
|
155
155
|
);
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
|
+
private sheetExists = async (
|
|
159
|
+
spreadsheetUrl: string,
|
|
160
|
+
sheetName: string,
|
|
161
|
+
): Promise<boolean> => {
|
|
162
|
+
const sheets = this.sheetsClient;
|
|
163
|
+
const spreadsheetId = this.getSpreadsheetId(spreadsheetUrl);
|
|
164
|
+
const response = await sheets.spreadsheets.get({ spreadsheetId });
|
|
165
|
+
if (response.status !== 200) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
`Failed to get sheet: ${response.status}. ${JSON.stringify(response.data)}`,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return (response.data.sheets ?? []).some(
|
|
171
|
+
(sheet) => sheet.properties?.title === sheetName,
|
|
172
|
+
);
|
|
173
|
+
};
|
|
158
174
|
createNewSheetIfNotExists = async (
|
|
159
175
|
spreadsheetUrl: string,
|
|
160
176
|
sheetName: string,
|
|
161
177
|
): Promise<void> => {
|
|
162
178
|
const sheets = this.sheetsClient;
|
|
163
179
|
const spreadsheetId = this.getSpreadsheetId(spreadsheetUrl);
|
|
164
|
-
|
|
165
|
-
if (sheet !== null) {
|
|
180
|
+
if (await this.sheetExists(spreadsheetUrl, sheetName)) {
|
|
166
181
|
return;
|
|
167
182
|
}
|
|
168
183
|
const response = await sheets.spreadsheets.batchUpdate({
|
|
@@ -132,7 +132,7 @@ describe('LocalStorageRepository', () => {
|
|
|
132
132
|
testCases.forEach(({ name, params }) => {
|
|
133
133
|
test(name, () => {
|
|
134
134
|
if (fs.existsSync(params[0])) {
|
|
135
|
-
fs.
|
|
135
|
+
fs.rmSync(params[0], { recursive: true });
|
|
136
136
|
}
|
|
137
137
|
repository.mkdir(...params);
|
|
138
138
|
expect(fs.existsSync(params[0])).toBe(true);
|
|
@@ -59,11 +59,11 @@ describe('OauthTokenSelectUseCase', () => {
|
|
|
59
59
|
expect(result.selected?.token).toBe('fake-token-soon');
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
it('excludes a token whose 5h window is less than
|
|
62
|
+
it('excludes a token whose 5h window is less than 25% free', () => {
|
|
63
63
|
const result = useCase.run(
|
|
64
64
|
[
|
|
65
|
-
candidate('busy5h', snapshot({ fiveHourUtilization: 0.
|
|
66
|
-
candidate('ok', snapshot({ fiveHourUtilization: 0.
|
|
65
|
+
candidate('busy5h', snapshot({ fiveHourUtilization: 0.76 })),
|
|
66
|
+
candidate('ok', snapshot({ fiveHourUtilization: 0.75 })),
|
|
67
67
|
],
|
|
68
68
|
NOW,
|
|
69
69
|
);
|
|
@@ -74,20 +74,22 @@ describe('OauthTokenSelectUseCase', () => {
|
|
|
74
74
|
expect(busy?.exclusionReason).toContain('5h window');
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
it('treats exactly
|
|
77
|
+
it('treats exactly 75% used 5h utilization as eligible (boundary)', () => {
|
|
78
78
|
const result = useCase.run(
|
|
79
|
-
[candidate('boundary', snapshot({ fiveHourUtilization: 0.
|
|
79
|
+
[candidate('boundary', snapshot({ fiveHourUtilization: 0.75 }))],
|
|
80
80
|
NOW,
|
|
81
81
|
);
|
|
82
82
|
|
|
83
83
|
expect(result.selected?.name).toBe('boundary');
|
|
84
|
+
const boundary = result.metrics.find((m) => m.name === 'boundary');
|
|
85
|
+
expect(boundary?.fiveHourFreeRatio).toBe(0.25);
|
|
84
86
|
});
|
|
85
87
|
|
|
86
|
-
it('excludes a token whose 7d window is less than
|
|
88
|
+
it('excludes a token whose 7d window is less than 3% free', () => {
|
|
87
89
|
const result = useCase.run(
|
|
88
90
|
[
|
|
89
|
-
candidate('busy7d', snapshot({ sevenDayUtilization: 0.
|
|
90
|
-
candidate('ok', snapshot({ sevenDayUtilization: 0.
|
|
91
|
+
candidate('busy7d', snapshot({ sevenDayUtilization: 0.98 })),
|
|
92
|
+
candidate('ok', snapshot({ sevenDayUtilization: 0.97 })),
|
|
91
93
|
],
|
|
92
94
|
NOW,
|
|
93
95
|
);
|
|
@@ -98,13 +100,33 @@ describe('OauthTokenSelectUseCase', () => {
|
|
|
98
100
|
expect(busy?.exclusionReason).toContain('7d window');
|
|
99
101
|
});
|
|
100
102
|
|
|
101
|
-
it('treats
|
|
103
|
+
it('treats exactly 97% used 7d utilization as eligible (boundary)', () => {
|
|
102
104
|
const result = useCase.run(
|
|
103
|
-
[candidate('boundary', snapshot({ sevenDayUtilization: 0.
|
|
105
|
+
[candidate('boundary', snapshot({ sevenDayUtilization: 0.97 }))],
|
|
104
106
|
NOW,
|
|
105
107
|
);
|
|
106
108
|
|
|
107
109
|
expect(result.selected?.name).toBe('boundary');
|
|
110
|
+
const boundary = result.metrics.find((m) => m.name === 'boundary');
|
|
111
|
+
expect(boundary?.sevenDayFreeRatio).toBeCloseTo(0.03, 9);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('proceeds when 5h is exactly 25% free and 7d is exactly 3% free (combined boundary)', () => {
|
|
115
|
+
const result = useCase.run(
|
|
116
|
+
[
|
|
117
|
+
candidate(
|
|
118
|
+
'boundary',
|
|
119
|
+
snapshot({ fiveHourUtilization: 0.75, sevenDayUtilization: 0.97 }),
|
|
120
|
+
),
|
|
121
|
+
],
|
|
122
|
+
NOW,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
expect(result.selected?.name).toBe('boundary');
|
|
126
|
+
const boundary = result.metrics.find((m) => m.name === 'boundary');
|
|
127
|
+
expect(boundary?.eligible).toBe(true);
|
|
128
|
+
expect(boundary?.fiveHourFreeRatio).toBe(0.25);
|
|
129
|
+
expect(boundary?.sevenDayFreeRatio).toBeCloseTo(0.03, 9);
|
|
108
130
|
});
|
|
109
131
|
|
|
110
132
|
it('treats a token with no snapshot as fully free', () => {
|
|
@@ -165,7 +187,7 @@ describe('OauthTokenSelectUseCase', () => {
|
|
|
165
187
|
const result = useCase.run(
|
|
166
188
|
[
|
|
167
189
|
candidate('busy', snapshot({ fiveHourUtilization: 0.9 })),
|
|
168
|
-
candidate('alsoBusy', snapshot({ sevenDayUtilization: 0.
|
|
190
|
+
candidate('alsoBusy', snapshot({ sevenDayUtilization: 0.98 })),
|
|
169
191
|
],
|
|
170
192
|
NOW,
|
|
171
193
|
);
|
|
@@ -41,8 +41,8 @@ export type OauthTokenSelectResult = {
|
|
|
41
41
|
const SECONDS_PER_DAY = 86400;
|
|
42
42
|
const SEVEN_DAYS_IN_SECONDS = 7 * SECONDS_PER_DAY;
|
|
43
43
|
|
|
44
|
-
export const FIVE_HOUR_MIN_FREE_RATIO = 0.
|
|
45
|
-
export const SEVEN_DAY_MIN_FREE_RATIO = 0.
|
|
44
|
+
export const FIVE_HOUR_MIN_FREE_RATIO = 0.25;
|
|
45
|
+
export const SEVEN_DAY_MIN_FREE_RATIO = 0.03;
|
|
46
46
|
|
|
47
47
|
export const selectWeightedCandidate = <Entry>(
|
|
48
48
|
eligible: Entry[],
|
|
@@ -72,6 +72,7 @@ export declare class GoogleSpreadsheetRepository implements SpreadsheetRepositor
|
|
|
72
72
|
getSpreadsheetId: (spreadsheetUrl: string) => string;
|
|
73
73
|
getSheet: (spreadsheetUrl: string, sheetName: string) => Promise<string[][] | null>;
|
|
74
74
|
updateCell: (spreadsheetUrl: string, sheetName: string, row: number, column: number, value: string) => Promise<void>;
|
|
75
|
+
private sheetExists;
|
|
75
76
|
createNewSheetIfNotExists: (spreadsheetUrl: string, sheetName: string) => Promise<void>;
|
|
76
77
|
appendSheetValues: (spreadsheetUrl: string, sheetName: string, values: string[][]) => Promise<void>;
|
|
77
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoogleSpreadsheetRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GoogleSpreadsheetRepository.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"GoogleSpreadsheetRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GoogleSpreadsheetRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,8 +28,8 @@ export type OauthTokenSelectResult = {
|
|
|
28
28
|
selected: OauthTokenCandidate | null;
|
|
29
29
|
metrics: OauthTokenCandidateMetrics[];
|
|
30
30
|
};
|
|
31
|
-
export declare const FIVE_HOUR_MIN_FREE_RATIO = 0.
|
|
32
|
-
export declare const SEVEN_DAY_MIN_FREE_RATIO = 0.
|
|
31
|
+
export declare const FIVE_HOUR_MIN_FREE_RATIO = 0.25;
|
|
32
|
+
export declare const SEVEN_DAY_MIN_FREE_RATIO = 0.03;
|
|
33
33
|
export declare const selectWeightedCandidate: <Entry>(eligible: Entry[], candidateOf: (entry: Entry) => OauthTokenCandidate, deterministicBest: Entry, random: SelectionRandom) => Entry;
|
|
34
34
|
export declare class OauthTokenSelectUseCase {
|
|
35
35
|
run: (candidates: OauthTokenCandidate[], nowEpochSeconds: number, random?: SelectionRandom) => OauthTokenSelectResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OauthTokenSelectUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/OauthTokenSelectUseCase.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC1C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC;AAE3C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,iBAAiB,GAAI,WAAW,mBAAmB,KAAG,MAGlE,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACvC,CAAC;AAKF,eAAO,MAAM,wBAAwB,
|
|
1
|
+
{"version":3,"file":"OauthTokenSelectUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/OauthTokenSelectUseCase.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC1C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC;AAE3C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,iBAAiB,GAAI,WAAW,mBAAmB,KAAG,MAGlE,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACvC,CAAC;AAKF,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C,eAAO,MAAM,uBAAuB,GAAI,KAAK,EAC3C,UAAU,KAAK,EAAE,EACjB,aAAa,CAAC,KAAK,EAAE,KAAK,KAAK,mBAAmB,EAClD,mBAAmB,KAAK,EACxB,QAAQ,eAAe,KACtB,KAoBF,CAAC;AAEF,qBAAa,uBAAuB;IAClC,GAAG,GACD,YAAY,mBAAmB,EAAE,EACjC,iBAAiB,MAAM,EACvB,SAAQ,eAA6B,KACpC,sBAAsB,CA2BvB;IAEF,OAAO,CAAC,QAAQ,CAiCd;IAEF,OAAO,CAAC,eAAe,CAuBrB;IAEF,OAAO,CAAC,iBAAiB,CAWvB;IAEF,OAAO,CAAC,iBAAiB,CAWvB;IAEF,OAAO,CAAC,gBAAgB,CActB;IAEF,OAAO,CAAC,aAAa,CAGwC;IAE7D,OAAO,CAAC,wBAAwB,CAG9B;IAEF,OAAO,CAAC,SAAS,CAAsD;CACxE"}
|