@simplysm/sd-claude 14.0.50 → 14.0.52
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/claude/references/sd-frontend-design.md +10 -9
- package/claude/references/sd-simplysm-v14/angular/README.md +497 -0
- package/claude/references/sd-simplysm-v14/angular/bootstrap/provide-sd-angular.md +37 -0
- package/claude/references/sd-simplysm-v14/angular/bootstrap/sd-angular-config-provider.md +16 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-command-directive.md +27 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-events.md +25 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-intersection-directive.md +36 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-invalid.md +24 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-resize-directive.md +42 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-ripple.md +23 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-router-link.md +38 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-show-effect.md +18 -0
- package/claude/references/sd-simplysm-v14/angular/directives/sd-typed-template.md +69 -0
- package/claude/references/sd-simplysm-v14/angular/features/sd-address-search-modal.md +50 -0
- package/claude/references/sd-simplysm-v14/angular/features/sd-permission-table.md +20 -0
- package/claude/references/sd-simplysm-v14/angular/features/sd-shared-data-components.md +158 -0
- package/claude/references/sd-simplysm-v14/angular/features/sd-tiptap-editor.md +26 -0
- package/claude/references/sd-simplysm-v14/angular/pipes/format-pipe.md +41 -0
- package/claude/references/sd-simplysm-v14/angular/plugins/sd-global-error-handler.md +23 -0
- package/claude/references/sd-simplysm-v14/angular/plugins/sd-option-event-plugin.md +34 -0
- package/claude/references/sd-simplysm-v14/angular/provider-types/sd-menu.md +65 -0
- package/claude/references/sd-simplysm-v14/angular/provider-types/sd-modal-content-def.md +148 -0
- package/claude/references/sd-simplysm-v14/angular/provider-types/sd-toast-content-def.md +73 -0
- package/claude/references/sd-simplysm-v14/angular/provider-types/shared-data-base.md +59 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-activated-modal-provider.md +34 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-app-structure-provider.md +81 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-busy-provider.md +18 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-file-dialog-provider.md +40 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-local-storage-provider.md +20 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-modal-provider.md +67 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-navigate-window-provider.md +18 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-print-provider.md +25 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-service-client-factory-provider.md +43 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-shared-data-provider.md +64 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-system-config-provider.md +46 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-system-log-provider.md +18 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-theme-provider.md +38 -0
- package/claude/references/sd-simplysm-v14/angular/providers/sd-toast-provider.md +65 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/_common-rules.md +336 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-detail/extension-a-edit-save.md +191 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-detail/extension-b-delete-restore.md +103 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-detail/extension-c-modal-view.md +198 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-detail/extension-d-control-view.md +109 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-detail/extension-e-auxiliary.md +87 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-detail/extension-f-complex-detail.md +202 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-detail.md +280 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list/extension-a-inline-edit.md +386 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list/extension-b-selection.md +215 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list/extension-c-inline-delete.md +64 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list/extension-d-select-modal.md +193 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list/extension-e-readonly-modal.md +140 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list/extension-f-modal-edit.md +123 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list/extension-g-excel.md +145 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/crud-list.md +377 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/data-select-button.md +368 -0
- package/claude/references/sd-simplysm-v14/angular/recipes/page-modal-container.md +238 -0
- package/claude/references/sd-simplysm-v14/angular/styling/classes.md +149 -0
- package/claude/references/sd-simplysm-v14/angular/styling/mixins.md +100 -0
- package/claude/references/sd-simplysm-v14/angular/styling/themes.md +35 -0
- package/claude/references/sd-simplysm-v14/angular/styling/variables.md +147 -0
- package/claude/references/sd-simplysm-v14/angular/type-utilities/directive-input-signals.md +232 -0
- package/claude/references/sd-simplysm-v14/angular/ui-data/sd-list.md +37 -0
- package/claude/references/sd-simplysm-v14/angular/ui-data/sd-sheet.md +212 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-additional-button.md +26 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-anchor.md +31 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-button.md +103 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-checkbox-group.md +39 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-checkbox.md +81 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-date-range-picker.md +27 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-form.md +89 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-modal-select-button.md +54 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-numpad.md +26 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-range.md +26 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-select.md +68 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-shared-data-select.md +52 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-state-preset.md +37 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-switch.md +27 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-textarea.md +33 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-textfield.md +145 -0
- package/claude/references/sd-simplysm-v14/angular/ui-layout/sd-dock-container.md +64 -0
- package/claude/references/sd-simplysm-v14/angular/ui-layout/sd-dock.md +37 -0
- package/claude/references/sd-simplysm-v14/angular/ui-layout/sd-gap.md +26 -0
- package/claude/references/sd-simplysm-v14/angular/ui-layout/sd-kanban-board.md +96 -0
- package/claude/references/sd-simplysm-v14/angular/ui-layout/sd-kanban-lane.md +34 -0
- package/claude/references/sd-simplysm-v14/angular/ui-layout/sd-kanban.md +29 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-collapse.md +35 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-pagination.md +26 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-sidebar-container.md +49 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-sidebar-menu.md +22 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-sidebar-user.md +43 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-tab.md +51 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-topbar-container.md +97 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-topbar-menu.md +23 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-topbar-user.md +38 -0
- package/claude/references/sd-simplysm-v14/angular/ui-navigation/sd-topbar.md +30 -0
- package/claude/references/sd-simplysm-v14/angular/ui-overlay/sd-busy-container.md +69 -0
- package/claude/references/sd-simplysm-v14/angular/ui-overlay/sd-confirm-modal.md +30 -0
- package/claude/references/sd-simplysm-v14/angular/ui-overlay/sd-dropdown.md +40 -0
- package/claude/references/sd-simplysm-v14/angular/ui-overlay/sd-modal.md +34 -0
- package/claude/references/sd-simplysm-v14/angular/ui-overlay/sd-prompt-modal.md +30 -0
- package/claude/references/sd-simplysm-v14/angular/ui-overlay/sd-toast.md +35 -0
- package/claude/references/sd-simplysm-v14/angular/ui-visual/sd-barcode.md +36 -0
- package/claude/references/sd-simplysm-v14/angular/ui-visual/sd-calendar.md +34 -0
- package/claude/references/sd-simplysm-v14/angular/ui-visual/sd-echarts.md +32 -0
- package/claude/references/sd-simplysm-v14/angular/ui-visual/sd-label.md +24 -0
- package/claude/references/sd-simplysm-v14/angular/ui-visual/sd-note.md +23 -0
- package/claude/references/sd-simplysm-v14/angular/ui-visual/sd-progress.md +23 -0
- package/claude/references/sd-simplysm-v14/angular/utils/inject-routing-signals.md +161 -0
- package/claude/references/sd-simplysm-v14/angular/utils/inject-sd-system-config-resource.md +35 -0
- package/claude/references/sd-simplysm-v14/angular/utils/mark.md +43 -0
- package/claude/references/sd-simplysm-v14/angular/utils/selection-managers.md +96 -0
- package/claude/references/sd-simplysm-v14/angular/utils/set-safe-style.md +19 -0
- package/claude/references/sd-simplysm-v14/angular/utils/setup-functions.md +93 -0
- package/claude/references/sd-simplysm-v14/capacitor-plugin-auto-update/README.md +38 -0
- package/claude/references/sd-simplysm-v14/capacitor-plugin-auto-update/apk-installer/apk-installer.md +115 -0
- package/claude/references/sd-simplysm-v14/capacitor-plugin-auto-update/auto-update/auto-update.md +113 -0
- package/claude/references/sd-simplysm-v14/capacitor-plugin-file-system/README.md +197 -0
- package/claude/references/sd-simplysm-v14/capacitor-plugin-intent/README.md +235 -0
- package/claude/references/sd-simplysm-v14/capacitor-plugin-usb-storage/README.md +251 -0
- package/claude/references/sd-simplysm-v14/core-browser/README.md +52 -0
- package/claude/references/sd-simplysm-v14/core-browser/extensions/copy-paste.md +59 -0
- package/claude/references/sd-simplysm-v14/core-browser/extensions/element-prototype-extensions.md +137 -0
- package/claude/references/sd-simplysm-v14/core-browser/extensions/get-bounds.md +84 -0
- package/claude/references/sd-simplysm-v14/core-browser/utils/download-blob.md +59 -0
- package/claude/references/sd-simplysm-v14/core-browser/utils/fetch-url-bytes.md +91 -0
- package/claude/references/sd-simplysm-v14/core-browser/utils/indexed-db-store.md +131 -0
- package/claude/references/sd-simplysm-v14/core-browser/utils/indexed-db-virtual-fs.md +121 -0
- package/claude/references/sd-simplysm-v14/core-browser/utils/open-file-dialog.md +60 -0
- package/claude/references/sd-simplysm-v14/core-common/README.md +179 -0
- package/claude/references/sd-simplysm-v14/core-common/errors/argument-error.md +26 -0
- package/claude/references/sd-simplysm-v14/core-common/errors/not-implemented-error.md +33 -0
- package/claude/references/sd-simplysm-v14/core-common/errors/sd-error.md +38 -0
- package/claude/references/sd-simplysm-v14/core-common/errors/timeout-error.md +36 -0
- package/claude/references/sd-simplysm-v14/core-common/extensions/array.md +125 -0
- package/claude/references/sd-simplysm-v14/core-common/extensions/map.md +43 -0
- package/claude/references/sd-simplysm-v14/core-common/extensions/set.md +35 -0
- package/claude/references/sd-simplysm-v14/core-common/features/debounce-queue.md +48 -0
- package/claude/references/sd-simplysm-v14/core-common/features/event-emitter.md +52 -0
- package/claude/references/sd-simplysm-v14/core-common/features/serial-queue.md +44 -0
- package/claude/references/sd-simplysm-v14/core-common/type-utils/common-types.md +100 -0
- package/claude/references/sd-simplysm-v14/core-common/type-utils/env.md +42 -0
- package/claude/references/sd-simplysm-v14/core-common/types/date-only.md +86 -0
- package/claude/references/sd-simplysm-v14/core-common/types/date-time.md +106 -0
- package/claude/references/sd-simplysm-v14/core-common/types/lazy-gc-map.md +59 -0
- package/claude/references/sd-simplysm-v14/core-common/types/time.md +62 -0
- package/claude/references/sd-simplysm-v14/core-common/types/uuid.md +41 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/bytes.md +36 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/dt.md +60 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/err.md +26 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/json.md +58 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/num.md +56 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/obj.md +107 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/path.md +30 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/primitive.md +28 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/str.md +63 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/template-strings.md +49 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/transfer.md +35 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/wait.md +35 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/xml.md +49 -0
- package/claude/references/sd-simplysm-v14/core-common/utils/zip-archive.md +77 -0
- package/claude/references/sd-simplysm-v14/core-node/README.md +59 -0
- package/claude/references/sd-simplysm-v14/core-node/features/fs-watcher.md +110 -0
- package/claude/references/sd-simplysm-v14/core-node/logging/create-file-reporter.md +78 -0
- package/claude/references/sd-simplysm-v14/core-node/logging/pretty-reporter.md +38 -0
- package/claude/references/sd-simplysm-v14/core-node/logging/setup-consola.md +77 -0
- package/claude/references/sd-simplysm-v14/core-node/utils/cpx.md +128 -0
- package/claude/references/sd-simplysm-v14/core-node/utils/fsx.md +168 -0
- package/claude/references/sd-simplysm-v14/core-node/utils/pathx.md +73 -0
- package/claude/references/sd-simplysm-v14/core-node/worker/create-worker.md +85 -0
- package/claude/references/sd-simplysm-v14/core-node/worker/worker.md +160 -0
- package/claude/references/sd-simplysm-v14/excel/README.md +66 -0
- package/claude/references/sd-simplysm-v14/excel/core-classes/excel-cell.md +79 -0
- package/claude/references/sd-simplysm-v14/excel/core-classes/excel-col.md +36 -0
- package/claude/references/sd-simplysm-v14/excel/core-classes/excel-row.md +34 -0
- package/claude/references/sd-simplysm-v14/excel/core-classes/excel-workbook.md +93 -0
- package/claude/references/sd-simplysm-v14/excel/core-classes/excel-worksheet.md +147 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-address-point.md +33 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-style-options.md +57 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-value-type.md +28 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml-content-type-data.md +23 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml-drawing-data.md +29 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml-relationship-data.md +39 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml-shared-string-data.md +42 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml-style-data.md +97 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml-workbook-data.md +22 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml-worksheet-data.md +68 -0
- package/claude/references/sd-simplysm-v14/excel/types/excel-xml.md +15 -0
- package/claude/references/sd-simplysm-v14/excel/utilities/excel-utils.md +101 -0
- package/claude/references/sd-simplysm-v14/excel/wrapper/excel-wrapper.md +108 -0
- package/claude/references/sd-simplysm-v14/lint/README.md +183 -0
- package/claude/references/sd-simplysm-v14/orm-common/README.md +156 -0
- package/claude/references/sd-simplysm-v14/orm-common/core/db-context.md +208 -0
- package/claude/references/sd-simplysm-v14/orm-common/core/db-transaction-error.md +64 -0
- package/claude/references/sd-simplysm-v14/orm-common/expression/expr-unit.md +62 -0
- package/claude/references/sd-simplysm-v14/orm-common/expression/expr.md +198 -0
- package/claude/references/sd-simplysm-v14/orm-common/models/migration.md +37 -0
- package/claude/references/sd-simplysm-v14/orm-common/query-builder/create-query-builder.md +80 -0
- package/claude/references/sd-simplysm-v14/orm-common/queryable-executable/executable.md +54 -0
- package/claude/references/sd-simplysm-v14/orm-common/queryable-executable/parse-search-query.md +75 -0
- package/claude/references/sd-simplysm-v14/orm-common/queryable-executable/queryable.md +238 -0
- package/claude/references/sd-simplysm-v14/orm-common/schema-builders/column-builder.md +63 -0
- package/claude/references/sd-simplysm-v14/orm-common/schema-builders/foreign-key-builder.md +137 -0
- package/claude/references/sd-simplysm-v14/orm-common/schema-builders/index-builder.md +54 -0
- package/claude/references/sd-simplysm-v14/orm-common/schema-builders/procedure.md +67 -0
- package/claude/references/sd-simplysm-v14/orm-common/schema-builders/table.md +95 -0
- package/claude/references/sd-simplysm-v14/orm-common/schema-builders/view.md +71 -0
- package/claude/references/sd-simplysm-v14/orm-common/types/data-type.md +146 -0
- package/claude/references/sd-simplysm-v14/orm-common/types/dialect.md +151 -0
- package/claude/references/sd-simplysm-v14/orm-common/types/expr.md +175 -0
- package/claude/references/sd-simplysm-v14/orm-common/types/parse-query-result.md +58 -0
- package/claude/references/sd-simplysm-v14/orm-common/types/query-def.md +224 -0
- package/claude/references/sd-simplysm-v14/orm-node/README.md +65 -0
- package/claude/references/sd-simplysm-v14/orm-node/connections/mssql-db-conn.md +85 -0
- package/claude/references/sd-simplysm-v14/orm-node/connections/mysql-db-conn.md +83 -0
- package/claude/references/sd-simplysm-v14/orm-node/connections/postgresql-db-conn.md +86 -0
- package/claude/references/sd-simplysm-v14/orm-node/core/create-db-conn.md +62 -0
- package/claude/references/sd-simplysm-v14/orm-node/core/create-orm.md +107 -0
- package/claude/references/sd-simplysm-v14/orm-node/core/node-db-context-executor.md +50 -0
- package/claude/references/sd-simplysm-v14/orm-node/types/db-conn-config.md +91 -0
- package/claude/references/sd-simplysm-v14/orm-node/types/db-conn-constants.md +33 -0
- package/claude/references/sd-simplysm-v14/orm-node/types/db-conn.md +60 -0
- package/claude/references/sd-simplysm-v14/orm-node/types/get-dialect-from-config.md +17 -0
- package/{README.md → claude/references/sd-simplysm-v14/sd-claude/README.md} +85 -84
- package/{docs → claude/references/sd-simplysm-v14/sd-claude}/assets.md +2 -2
- package/{docs → claude/references/sd-simplysm-v14/sd-claude}/hooks.md +15 -1
- package/claude/references/sd-simplysm-v14/sd-cli/README.md +138 -0
- package/claude/references/sd-simplysm-v14/sd-cli/angular-vite-plugin/sd-angular-plugin.md +60 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/build-target.md +31 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/npm-config.md +27 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-browser-support-config.md +19 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-build-package-config.md +21 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-capacitor-config.md +109 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-client-package-config.md +33 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-config.md +78 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-electron-config.md +27 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-package-config.md +18 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-post-publish-script-config.md +19 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-publish-config.md +72 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-pwa-config.md +41 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-scripts-package-config.md +19 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-server-package-config.md +32 -0
- package/claude/references/sd-simplysm-v14/sd-cli/config/sd-watch-hook-config.md +19 -0
- package/claude/references/sd-simplysm-v14/sd-cli/ts-compiler/sd-ts-compiler.md +158 -0
- package/claude/references/sd-simplysm-v14/service-client/README.md +74 -0
- package/claude/references/sd-simplysm-v14/service-client/features/event-client.md +93 -0
- package/claude/references/sd-simplysm-v14/service-client/features/file-client.md +63 -0
- package/claude/references/sd-simplysm-v14/service-client/features/orm-client-connector.md +89 -0
- package/claude/references/sd-simplysm-v14/service-client/features/orm-client-db-context-executor.md +31 -0
- package/claude/references/sd-simplysm-v14/service-client/main/service-client.md +206 -0
- package/claude/references/sd-simplysm-v14/service-client/protocol/client-protocol-wrapper.md +64 -0
- package/claude/references/sd-simplysm-v14/service-client/transport/service-transport.md +68 -0
- package/claude/references/sd-simplysm-v14/service-client/transport/socket-provider.md +100 -0
- package/claude/references/sd-simplysm-v14/service-client/types/blob-input.md +7 -0
- package/claude/references/sd-simplysm-v14/service-client/types/browser-worker.md +47 -0
- package/claude/references/sd-simplysm-v14/service-client/types/file-collection.md +21 -0
- package/claude/references/sd-simplysm-v14/service-client/types/service-connection-options.md +22 -0
- package/claude/references/sd-simplysm-v14/service-client/types/service-progress.md +39 -0
- package/claude/references/sd-simplysm-v14/service-common/README.md +161 -0
- package/claude/references/sd-simplysm-v14/service-common/app-structure/app-structure-item.md +107 -0
- package/claude/references/sd-simplysm-v14/service-common/app-structure/get-flat-permissions.md +57 -0
- package/claude/references/sd-simplysm-v14/service-common/app-structure/is-usable-modules-chain.md +23 -0
- package/claude/references/sd-simplysm-v14/service-common/app-structure/is-usable-modules.md +42 -0
- package/claude/references/sd-simplysm-v14/service-common/events/define-event.md +68 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/create-service-protocol.md +93 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/protocol-config.md +21 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-add-event-listener-message.md +23 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-auth-message.md +17 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-emit-event-message.md +21 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-error-message.md +29 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-event-message.md +21 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-get-event-listener-infos-message.md +19 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-message.md +52 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-progress-message.md +21 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-remove-event-listener-message.md +19 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-request-message.md +17 -0
- package/claude/references/sd-simplysm-v14/service-common/protocol/service-response-message.md +17 -0
- package/claude/references/sd-simplysm-v14/service-common/service-types/app-structure-service.md +15 -0
- package/claude/references/sd-simplysm-v14/service-common/service-types/auto-update-service.md +20 -0
- package/claude/references/sd-simplysm-v14/service-common/service-types/orm-service.md +61 -0
- package/claude/references/sd-simplysm-v14/service-common/types/service-upload-result.md +19 -0
- package/claude/references/sd-simplysm-v14/service-server/README.md +162 -0
- package/claude/references/sd-simplysm-v14/service-server/auth/auth-token-payload.md +18 -0
- package/claude/references/sd-simplysm-v14/service-server/auth/sign-jwt.md +30 -0
- package/claude/references/sd-simplysm-v14/service-server/auth/verify-jwt.md +35 -0
- package/claude/references/sd-simplysm-v14/service-server/core/auth.md +64 -0
- package/claude/references/sd-simplysm-v14/service-server/core/define-service.md +81 -0
- package/claude/references/sd-simplysm-v14/service-server/core/execute-service-method.md +43 -0
- package/claude/references/sd-simplysm-v14/service-server/core/service-context.md +79 -0
- package/claude/references/sd-simplysm-v14/service-server/legacy/handle-v1-connection.md +25 -0
- package/claude/references/sd-simplysm-v14/service-server/main/create-service-server.md +32 -0
- package/claude/references/sd-simplysm-v14/service-server/main/service-server.md +113 -0
- package/claude/references/sd-simplysm-v14/service-server/protocol/server-protocol-wrapper.md +35 -0
- package/claude/references/sd-simplysm-v14/service-server/services/app-structure-service.md +59 -0
- package/claude/references/sd-simplysm-v14/service-server/services/auto-update-service.md +34 -0
- package/claude/references/sd-simplysm-v14/service-server/services/orm-service.md +43 -0
- package/claude/references/sd-simplysm-v14/service-server/transport-http/handle-http-request.md +33 -0
- package/claude/references/sd-simplysm-v14/service-server/transport-http/handle-static-file.md +29 -0
- package/claude/references/sd-simplysm-v14/service-server/transport-http/handle-upload.md +33 -0
- package/claude/references/sd-simplysm-v14/service-server/transport-socket/service-socket.md +64 -0
- package/claude/references/sd-simplysm-v14/service-server/transport-socket/websocket-handler.md +57 -0
- package/claude/references/sd-simplysm-v14/service-server/types/service-server-options.md +36 -0
- package/claude/references/sd-simplysm-v14/service-server/utils/get-config.md +29 -0
- package/claude/references/sd-simplysm-v14/storage/README.md +99 -0
- package/claude/references/sd-simplysm-v14/storage/clients/ftp-storage-client.md +99 -0
- package/claude/references/sd-simplysm-v14/storage/clients/sftp-storage-client.md +108 -0
- package/claude/references/sd-simplysm-v14/storage/factory/storage-factory.md +114 -0
- package/claude/references/sd-simplysm-v14/storage/types/file-info.md +32 -0
- package/claude/references/sd-simplysm-v14/storage/types/storage-client.md +55 -0
- package/claude/references/sd-simplysm-v14/storage/types/storage-conn-config.md +34 -0
- package/claude/rules/sd-claude-rules.md +8 -8
- package/claude/rules/sd-simplysm-v14.md +33 -0
- package/claude/skills/sd-claude-docs/SKILL.md +41 -24
- package/claude/skills/sd-claude-docs/references/package-docs.md +240 -116
- package/claude/skills/sd-inner-debug/SKILL.md +1 -1
- package/claude/skills/sd-inner-review/SKILL.md +4 -2
- package/package.json +2 -3
- /package/{docs → claude/references/sd-simplysm-v14/sd-claude}/cli.md +0 -0
- /package/{docs → claude/references/sd-simplysm-v14/sd-claude}/scripts.md +0 -0
package/claude/references/sd-simplysm-v14/core-browser/extensions/element-prototype-extensions.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Element / HTMLElement Prototype Extensions
|
|
2
|
+
|
|
3
|
+
패키지를 임포트하면 사이드 이펙트로 `Element`와 `HTMLElement` 프로토타입에 메서드가 추가된다. 별도 등록 없이 `import "@simplysm/core-browser"` 또는 개별 모듈 임포트로 활성화된다.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- ✅ DOM 요소 검색/탐색이 필요할 때 (`findAll`, `findFirst`, `getParents`)
|
|
8
|
+
- ✅ 탭 이동 가능한 요소를 찾을 때 (`findTabbableParent`, `findFirstTabbableChild`)
|
|
9
|
+
- ✅ 요소 가시성/위치 확인이 필요할 때 (`isVisible`, `isOffsetElement`, `getRelativeOffset`)
|
|
10
|
+
- ✅ 강제 리페인트나 스크롤 조정이 필요할 때 (`repaint`, `scrollIntoViewIfNeeded`)
|
|
11
|
+
- ❌ 여러 요소의 경계 정보를 비동기로 조회 → [`getBounds`](./get-bounds.md)
|
|
12
|
+
- ❌ Node.js 환경 → DOM API가 없으므로 사용 불가
|
|
13
|
+
|
|
14
|
+
## Element Prototype Methods
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// 선택자와 일치하는 모든 하위 요소 검색. 빈 선택자 → 빈 배열.
|
|
18
|
+
element.findAll<TEl extends Element = Element>(selector: string): TEl[]
|
|
19
|
+
|
|
20
|
+
// 선택자와 일치하는 첫 번째 요소. 빈 선택자 → undefined.
|
|
21
|
+
element.findFirst<TEl extends Element = Element>(selector: string): TEl | undefined
|
|
22
|
+
|
|
23
|
+
// 요소를 첫 번째 자식으로 삽입. 삽입된 자식 요소를 반환.
|
|
24
|
+
element.prependChild<TEl extends Element>(child: TEl): TEl
|
|
25
|
+
|
|
26
|
+
// 모든 부모 요소 배열 (가장 가까운 것부터 먼 것 순서)
|
|
27
|
+
element.getParents(): Element[]
|
|
28
|
+
|
|
29
|
+
// 첫 번째 탭 이동 가능한 부모 요소 (tabbable 라이브러리 사용). 없으면 undefined.
|
|
30
|
+
element.findTabbableParent(): HTMLElement | undefined
|
|
31
|
+
|
|
32
|
+
// 첫 번째 탭 이동 가능한 자식 요소 (TreeWalker + tabbable 사용). 없으면 undefined.
|
|
33
|
+
element.findFirstTabbableChild(): HTMLElement | undefined
|
|
34
|
+
|
|
35
|
+
// position이 relative/absolute/fixed/sticky인지 확인
|
|
36
|
+
element.isOffsetElement(): boolean
|
|
37
|
+
|
|
38
|
+
// 화면에 보이는지 확인 (clientRects 존재 + visibility !== "hidden" + opacity !== "0")
|
|
39
|
+
element.isVisible(): boolean
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## HTMLElement Prototype Methods
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// 강제 리페인트. offsetHeight 접근으로 동기 reflow를 트리거한다.
|
|
46
|
+
htmlElement.repaint(): void
|
|
47
|
+
|
|
48
|
+
// 부모 요소 기준 상대 위치 계산. CSS top/left 속성에 바로 사용 가능한 좌표 반환.
|
|
49
|
+
// parent: HTMLElement 인스턴스 또는 CSS 선택자 문자열 (closest()로 탐색)
|
|
50
|
+
// border 두께, CSS transform 변환을 모두 포함하여 계산한다.
|
|
51
|
+
// 부모를 찾을 수 없으면 ArgumentError를 던진다.
|
|
52
|
+
htmlElement.getRelativeOffset(parent: HTMLElement | string): { top: number; left: number }
|
|
53
|
+
|
|
54
|
+
// offset 영역(고정 헤더/컬럼)에 가려진 경우 대상이 보이도록 스크롤 조정.
|
|
55
|
+
// target: 컨테이너 내 대상 위치 (offsetTop, offsetLeft)
|
|
56
|
+
// offset: 가려지면 안 되는 영역 크기 (기본값 { top: 0, left: 0 })
|
|
57
|
+
// 상단/좌측 방향만 처리. 하단/우측은 브라우저 기본 포커스 스크롤에 의존.
|
|
58
|
+
htmlElement.scrollIntoViewIfNeeded(
|
|
59
|
+
target: { top: number; left: number },
|
|
60
|
+
offset?: { top: number; left: number }
|
|
61
|
+
): void
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
### 최소 예제
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import "@simplysm/core-browser";
|
|
70
|
+
|
|
71
|
+
const container = document.querySelector(".container")!;
|
|
72
|
+
const buttons = container.findAll<HTMLButtonElement>("button");
|
|
73
|
+
const firstInput = container.findFirst<HTMLInputElement>("input[type=text]");
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 전형 예제 — 포커스 이동 가능한 요소 탐색
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import "@simplysm/core-browser";
|
|
80
|
+
|
|
81
|
+
// 현재 요소에서 가장 가까운 탭 이동 가능한 부모로 포커스 이동
|
|
82
|
+
function focusNearestTabbableParent(el: Element): void {
|
|
83
|
+
const tabbable = el.findTabbableParent();
|
|
84
|
+
if (tabbable != null) {
|
|
85
|
+
tabbable.focus();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 컨테이너 내 첫 번째 탭 이동 가능한 자식으로 포커스
|
|
90
|
+
function focusFirstChild(container: Element): void {
|
|
91
|
+
const child = container.findFirstTabbableChild();
|
|
92
|
+
if (child != null) {
|
|
93
|
+
child.focus();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 전형 예제 — 드롭다운 위치 계산
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import "@simplysm/core-browser";
|
|
102
|
+
|
|
103
|
+
function positionDropdown(trigger: HTMLElement, dropdown: HTMLElement): void {
|
|
104
|
+
// position: relative/absolute 부모를 찾아 상대 좌표 계산
|
|
105
|
+
const offset = trigger.getRelativeOffset(dropdown.offsetParent as HTMLElement);
|
|
106
|
+
dropdown.style.top = `${offset.top + trigger.offsetHeight}px`;
|
|
107
|
+
dropdown.style.left = `${offset.left}px`;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 🚫 Anti-patterns
|
|
112
|
+
|
|
113
|
+
### 빈 선택자로 findAll/findFirst 호출
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// ❌ 빈 문자열은 빈 배열/undefined를 반환하므로 의미 없는 호출
|
|
117
|
+
const els = container.findAll("");
|
|
118
|
+
|
|
119
|
+
// ✅ 빈 선택자 가능성이 있으면 호출 전에 검사
|
|
120
|
+
if (selector !== "") {
|
|
121
|
+
const els = container.findAll(selector);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**근거**: 내부에서 `trim()` 후 빈 문자열이면 즉시 빈 결과를 반환한다. 에러는 나지 않지만 불필요한 호출이다.
|
|
126
|
+
|
|
127
|
+
### getRelativeOffset에 존재하지 않는 선택자 전달
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// ❌ 선택자가 일치하지 않으면 ArgumentError 발생
|
|
131
|
+
element.getRelativeOffset(".nonexistent-class");
|
|
132
|
+
|
|
133
|
+
// ✅ 확실한 부모 요소를 직접 전달
|
|
134
|
+
element.getRelativeOffset(parentElement);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**근거**: 문자열을 전달하면 `closest()`로 탐색하므로, 일치하는 부모가 없으면 `ArgumentError`가 발생한다.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# `getBounds`
|
|
2
|
+
|
|
3
|
+
IntersectionObserver를 사용하여 여러 요소의 경계 정보를 비동기로 조회하는 함수. 뷰포트 기준 위치·크기가 필요할 때 사용한다.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- ✅ 여러 요소의 뷰포트 기준 위치/크기를 한 번에 조회할 때
|
|
8
|
+
- ✅ `getBoundingClientRect()`가 정확하지 않은 타이밍(예: 레이아웃 직후)에 안정적인 측정이 필요할 때
|
|
9
|
+
- ❌ 단일 요소의 즉시 측정 → `getBoundingClientRect()`로 충분
|
|
10
|
+
- ❌ 요소 가시성만 확인 → `element.isVisible()` 프로토타입 확장 사용
|
|
11
|
+
|
|
12
|
+
## Signature
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
export async function getBounds(
|
|
16
|
+
els: Element[],
|
|
17
|
+
timeout?: number, // 기본값: 5000 (ms)
|
|
18
|
+
): Promise<ElementBounds[]>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Parameters
|
|
22
|
+
|
|
23
|
+
| Param | Type | Description |
|
|
24
|
+
|-------|------|-------------|
|
|
25
|
+
| `els` | `Element[]` | 측정 대상 요소 배열. 중복은 자동 제거. 빈 배열이면 빈 결과 반환 |
|
|
26
|
+
| `timeout` | `number` | 타임아웃 밀리초. 기본값 5000. 시간 내에 모든 요소의 측정이 완료되지 않으면 `TimeoutError` 발생 |
|
|
27
|
+
|
|
28
|
+
## Returns
|
|
29
|
+
|
|
30
|
+
`Promise<ElementBounds[]>` — 입력 순서대로 정렬된 경계 정보 배열.
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### 최소 예제
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { getBounds } from "@simplysm/core-browser";
|
|
38
|
+
|
|
39
|
+
const elements = document.querySelectorAll(".card");
|
|
40
|
+
const bounds = await getBounds([...elements]);
|
|
41
|
+
// bounds[0].top, bounds[0].left, bounds[0].width, bounds[0].height
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 전형 예제 — 타임아웃 처리
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { getBounds } from "@simplysm/core-browser";
|
|
48
|
+
import { TimeoutError } from "@simplysm/core-common";
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const bounds = await getBounds(targetElements, 3000); // 3초 타임아웃
|
|
52
|
+
for (const b of bounds) {
|
|
53
|
+
// b.target: 원본 요소 참조
|
|
54
|
+
// b.top, b.left: 뷰포트 기준 좌표
|
|
55
|
+
// b.width, b.height: 요소 크기
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
if (err instanceof TimeoutError) {
|
|
59
|
+
// 요소가 DOM에서 제거되었거나 display:none인 경우 IntersectionObserver가 응답하지 않을 수 있음
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Related Types
|
|
65
|
+
|
|
66
|
+
### `ElementBounds`
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
export interface ElementBounds {
|
|
70
|
+
target: Element;
|
|
71
|
+
top: number;
|
|
72
|
+
left: number;
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
| Field | Type | Description |
|
|
79
|
+
|-------|------|-------------|
|
|
80
|
+
| `target` | `Element` | 측정 대상 요소 |
|
|
81
|
+
| `top` | `number` | 뷰포트 기준 상단 위치 |
|
|
82
|
+
| `left` | `number` | 뷰포트 기준 좌측 위치 |
|
|
83
|
+
| `width` | `number` | 요소 너비 |
|
|
84
|
+
| `height` | `number` | 요소 높이 |
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# `downloadBlob`
|
|
2
|
+
|
|
3
|
+
메모리의 Blob을 사용자 파일로 다운로드하는 함수. `<a>` 태그 클릭 방식으로 동작한다.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- ✅ 메모리에서 생성한 데이터(엑셀, CSV, 바이너리 등)를 파일로 다운로드할 때
|
|
8
|
+
- ❌ URL에서 파일 다운로드 → [`fetchUrlBytes`](./fetch-url-bytes.md)로 먼저 가져온 후 사용하거나, `<a href>` 직접 사용
|
|
9
|
+
|
|
10
|
+
## Signature
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
export function downloadBlob(blob: Blob, fileName: string): void
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Parameters
|
|
17
|
+
|
|
18
|
+
| Param | Type | Description |
|
|
19
|
+
|-------|------|-------------|
|
|
20
|
+
| `blob` | `Blob` | 다운로드할 Blob 객체 |
|
|
21
|
+
| `fileName` | `string` | 저장할 파일명. 파일시스템 금지 문자(`/ \ : * ? " < > \|`), 제어문자, Windows 예약어(CON, PRN 등)는 `sanitize-filename`으로 자동 제거. 제거 후 빈 문자열이면 `"download"`로 대체 |
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### 최소 예제
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { downloadBlob } from "@simplysm/core-browser";
|
|
29
|
+
|
|
30
|
+
const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
|
|
31
|
+
const blob = new Blob([data], { type: "application/octet-stream" });
|
|
32
|
+
downloadBlob(blob, "output.bin");
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 전형 예제 — JSON 데이터 다운로드
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { downloadBlob } from "@simplysm/core-browser";
|
|
39
|
+
|
|
40
|
+
const jsonStr = JSON.stringify(exportData, null, 2);
|
|
41
|
+
const blob = new Blob([jsonStr], { type: "application/json" });
|
|
42
|
+
downloadBlob(blob, "export-data.json");
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🚫 Anti-patterns
|
|
46
|
+
|
|
47
|
+
### Object URL 수동 해제
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// ❌ downloadBlob은 내부에서 1초 후 자동으로 URL.revokeObjectURL을 호출함
|
|
51
|
+
const url = URL.createObjectURL(blob);
|
|
52
|
+
downloadBlob(blob, "file.txt");
|
|
53
|
+
URL.revokeObjectURL(url); // 불필요한 중복 해제
|
|
54
|
+
|
|
55
|
+
// ✅ downloadBlob만 호출하면 됨
|
|
56
|
+
downloadBlob(blob, "file.txt");
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**근거**: 내부에서 `setTimeout(() => URL.revokeObjectURL(url), 1000)`으로 자동 정리한다.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# `fetchUrlBytes`
|
|
2
|
+
|
|
3
|
+
URL에서 바이너리 데이터를 `Uint8Array`로 다운로드하는 함수. 진행 콜백을 지원한다.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- ✅ URL에서 바이너리 파일을 메모리로 가져올 때 (이미지, WASM, 압축 파일 등)
|
|
8
|
+
- ✅ 다운로드 진행률 표시가 필요할 때
|
|
9
|
+
- ❌ 텍스트/JSON 응답 → 표준 `fetch()` API 직접 사용
|
|
10
|
+
- ❌ 다운로드한 데이터를 바로 파일로 저장 → 이 함수로 가져온 후 [`downloadBlob`](./download-blob.md) 사용
|
|
11
|
+
|
|
12
|
+
## Signature
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
export async function fetchUrlBytes(
|
|
16
|
+
url: string,
|
|
17
|
+
options?: { onProgress?: (progress: DownloadProgress) => void },
|
|
18
|
+
): Promise<Uint8Array>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Parameters
|
|
22
|
+
|
|
23
|
+
| Param | Type | Description |
|
|
24
|
+
|-------|------|-------------|
|
|
25
|
+
| `url` | `string` | 다운로드 대상 URL |
|
|
26
|
+
| `options.onProgress` | `(progress: DownloadProgress) => void` | 진행 콜백. `Content-Length` 헤더가 있는 경우에만 호출됨 |
|
|
27
|
+
|
|
28
|
+
## Returns
|
|
29
|
+
|
|
30
|
+
`Promise<Uint8Array>` — 다운로드된 바이너리 데이터.
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### 최소 예제
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { fetchUrlBytes } from "@simplysm/core-browser";
|
|
38
|
+
|
|
39
|
+
const data = await fetchUrlBytes("/api/files/report.pdf");
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 전형 예제 — 진행률 표시
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { fetchUrlBytes } from "@simplysm/core-browser";
|
|
46
|
+
|
|
47
|
+
const data = await fetchUrlBytes("/api/files/large-file.zip", {
|
|
48
|
+
onProgress: (progress) => {
|
|
49
|
+
const percent = Math.round((progress.receivedLength / progress.contentLength) * 100);
|
|
50
|
+
updateProgressBar(percent);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 🚫 Anti-patterns
|
|
56
|
+
|
|
57
|
+
### Content-Length 없는 응답에서 진행률 의존
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// ❌ chunked encoding 응답은 Content-Length가 0이므로 onProgress가 호출되지 않음
|
|
61
|
+
const data = await fetchUrlBytes("/api/stream", {
|
|
62
|
+
onProgress: (p) => {
|
|
63
|
+
// contentLength가 0이면 이 콜백은 호출되지 않음
|
|
64
|
+
showProgress(p.receivedLength / p.contentLength);
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**근거**: `Content-Length` 헤더가 없거나 0이면 청크 수집 모드로 전환되며, 이 경우 `onProgress`가 호출되지 않는다.
|
|
70
|
+
|
|
71
|
+
## 에러 처리
|
|
72
|
+
|
|
73
|
+
- HTTP 응답이 실패하면 (`response.ok === false`) `Error` 발생: `"다운로드 실패: {status} {statusText}"`
|
|
74
|
+
- 응답 본문을 읽을 수 없으면 `Error` 발생: `"응답 본문을 읽을 수 없습니다"`
|
|
75
|
+
- 수신 데이터가 `Content-Length`를 초과하거나 부족하면 `Error` 발생
|
|
76
|
+
|
|
77
|
+
## Related Types
|
|
78
|
+
|
|
79
|
+
### `DownloadProgress`
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
export interface DownloadProgress {
|
|
83
|
+
receivedLength: number;
|
|
84
|
+
contentLength: number;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Field | Type | Description |
|
|
89
|
+
|-------|------|-------------|
|
|
90
|
+
| `receivedLength` | `number` | 현재까지 수신한 바이트 수 |
|
|
91
|
+
| `contentLength` | `number` | 전체 콘텐츠 길이 (Content-Length 헤더 값) |
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# `IndexedDbStore`
|
|
2
|
+
|
|
3
|
+
IndexedDB를 Promise 기반으로 래핑한 저수준 CRUD 클래스. 생성자에서 DB 이름, 버전, 스토어 설정을 받아 자기 완결적으로 동작한다.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- ✅ 브라우저에서 구조화된 데이터를 영속 저장할 때 (캐시, 오프라인 데이터 등)
|
|
8
|
+
- ✅ IndexedDB의 콜백 기반 API를 Promise로 사용하고 싶을 때
|
|
9
|
+
- ❌ 경로 기반 파일시스템 추상화가 필요 → [`IndexedDbVirtualFs`](./indexed-db-virtual-fs.md)
|
|
10
|
+
- ❌ 서버 측 데이터 저장 → `@simplysm/orm-node`
|
|
11
|
+
|
|
12
|
+
## Signature
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
export class IndexedDbStore {
|
|
16
|
+
constructor(dbName: string, dbVersion: number, storeConfigs: StoreConfig[])
|
|
17
|
+
|
|
18
|
+
open(): Promise<IDBDatabase>
|
|
19
|
+
withStore<TResult>(
|
|
20
|
+
storeName: string,
|
|
21
|
+
mode: IDBTransactionMode,
|
|
22
|
+
fn: (store: IDBObjectStore) => Promise<TResult>,
|
|
23
|
+
): Promise<TResult>
|
|
24
|
+
get<TValue>(storeName: string, key: IDBValidKey): Promise<TValue | undefined>
|
|
25
|
+
put(storeName: string, value: unknown): Promise<void>
|
|
26
|
+
delete(storeName: string, key: IDBValidKey): Promise<void>
|
|
27
|
+
getAll<TItem>(storeName: string): Promise<TItem[]>
|
|
28
|
+
close(): void
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Members
|
|
33
|
+
|
|
34
|
+
| Member | Kind | Description |
|
|
35
|
+
|--------|------|-------------|
|
|
36
|
+
| `constructor` | method | DB 이름, 버전, 스토어 설정으로 인스턴스 생성. `open()` 시 설정에 없는 스토어는 자동 생성 |
|
|
37
|
+
| `open` | method | DB 연결. 중복 호출에 안전 (이미 열려 있으면 기존 인스턴스 반환). 다른 연결에 의해 차단되면 에러 |
|
|
38
|
+
| `withStore` | method | 트랜잭션을 열고 `fn`을 실행. fn이 에러를 던지면 트랜잭션을 abort |
|
|
39
|
+
| `get` | method | 키로 단일 항목 조회. 없으면 `undefined` |
|
|
40
|
+
| `put` | method | 항목 추가/갱신. value에 keyPath에 해당하는 필드가 포함되어야 함 |
|
|
41
|
+
| `delete` | method | 키로 항목 삭제 |
|
|
42
|
+
| `getAll` | method | 스토어의 모든 항목 조회 |
|
|
43
|
+
| `close` | method | DB 연결 닫기. 내부 상태 초기화 |
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
### 최소 예제
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { IndexedDbStore } from "@simplysm/core-browser";
|
|
51
|
+
|
|
52
|
+
const store = new IndexedDbStore("myDb", 1, [{ name: "items", keyPath: "id" }]);
|
|
53
|
+
|
|
54
|
+
await store.put("items", { id: "key1", value: "hello" });
|
|
55
|
+
const item = await store.get<{ id: string; value: string }>("items", "key1");
|
|
56
|
+
store.close();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 전형 예제 — 커스텀 트랜잭션
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { IndexedDbStore } from "@simplysm/core-browser";
|
|
63
|
+
|
|
64
|
+
const store = new IndexedDbStore("appDb", 2, [
|
|
65
|
+
{ name: "users", keyPath: "uid" },
|
|
66
|
+
{ name: "settings", keyPath: "key" },
|
|
67
|
+
]);
|
|
68
|
+
|
|
69
|
+
// withStore로 저수준 트랜잭션 제어
|
|
70
|
+
const count = await store.withStore("users", "readonly", async (objectStore) => {
|
|
71
|
+
return new Promise<number>((resolve, reject) => {
|
|
72
|
+
const req = objectStore.count();
|
|
73
|
+
req.onsuccess = () => resolve(req.result);
|
|
74
|
+
req.onerror = () => reject(req.error);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// 전체 항목 조회
|
|
79
|
+
const allUsers = await store.getAll<{ uid: string; name: string }>("users");
|
|
80
|
+
|
|
81
|
+
store.close();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 🚫 Anti-patterns
|
|
85
|
+
|
|
86
|
+
### close() 호출 누락
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// ❌ 연결을 닫지 않으면 다른 탭에서 DB 버전 업그레이드 시 차단됨
|
|
90
|
+
const store = new IndexedDbStore("db", 1, configs);
|
|
91
|
+
await store.put("items", data);
|
|
92
|
+
// close() 없이 방치
|
|
93
|
+
|
|
94
|
+
// ✅ 사용 후 반드시 close()
|
|
95
|
+
const store = new IndexedDbStore("db", 1, configs);
|
|
96
|
+
try {
|
|
97
|
+
await store.put("items", data);
|
|
98
|
+
} finally {
|
|
99
|
+
store.close();
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**근거**: IndexedDB는 `versionchange` 이벤트 시 열린 연결을 닫아야 다른 탭에서 스키마 업그레이드가 가능하다. 내부에서 `onversionchange` 핸들러가 자동으로 닫기는 하지만, 명시적 정리가 권장된다.
|
|
104
|
+
|
|
105
|
+
### keyPath 누락된 값으로 put
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// ❌ StoreConfig에 keyPath: "id"로 설정했는데 id 필드가 없음
|
|
109
|
+
await store.put("items", { name: "test" }); // IndexedDB DataError
|
|
110
|
+
|
|
111
|
+
// ✅ keyPath에 해당하는 필드를 반드시 포함
|
|
112
|
+
await store.put("items", { id: "1", name: "test" });
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**근거**: IndexedDB는 keyPath에 해당하는 필드가 없으면 `DataError`를 발생시킨다.
|
|
116
|
+
|
|
117
|
+
## Related Types
|
|
118
|
+
|
|
119
|
+
### `StoreConfig`
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
export interface StoreConfig {
|
|
123
|
+
name: string;
|
|
124
|
+
keyPath: string;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
| Field | Type | Description |
|
|
129
|
+
|-------|------|-------------|
|
|
130
|
+
| `name` | `string` | object store 이름 |
|
|
131
|
+
| `keyPath` | `string` | 기본 키 경로 |
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# `IndexedDbVirtualFs`
|
|
2
|
+
|
|
3
|
+
`IndexedDbStore` 위에 경로 기반 가상 파일시스템을 구현하는 클래스. 키는 `/path/to/file` 형태의 문자열이다.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- ✅ 브라우저에서 파일/디렉토리 계층 구조를 IndexedDB에 저장할 때
|
|
8
|
+
- ✅ 오프라인 캐시나 가상 파일시스템이 필요할 때
|
|
9
|
+
- ❌ 단순 키-값 저장 → [`IndexedDbStore`](./indexed-db-store.md)로 충분
|
|
10
|
+
- ❌ 실제 파일시스템 접근 → File System Access API 또는 서버 측 처리
|
|
11
|
+
|
|
12
|
+
## Signature
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
export class IndexedDbVirtualFs {
|
|
16
|
+
constructor(db: IndexedDbStore, storeName: string, keyField: string)
|
|
17
|
+
|
|
18
|
+
getEntry(fullKey: string): Promise<VirtualFsEntry | undefined>
|
|
19
|
+
putEntry(fullKey: string, kind: "file" | "dir", dataBase64?: string): Promise<void>
|
|
20
|
+
deleteByPrefix(keyPrefix: string): Promise<boolean>
|
|
21
|
+
listChildren(prefix: string): Promise<{ name: string; isDirectory: boolean }[]>
|
|
22
|
+
ensureDir(fullKeyBuilder: (path: string) => string, dirPath: string): Promise<void>
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Members
|
|
27
|
+
|
|
28
|
+
| Member | Kind | Description |
|
|
29
|
+
|--------|------|-------------|
|
|
30
|
+
| `constructor` | method | `IndexedDbStore` 인스턴스, 스토어 이름, 키 필드명을 주입받음 |
|
|
31
|
+
| `getEntry` | method | 경로에 해당하는 엔트리 조회. 없으면 `undefined` |
|
|
32
|
+
| `putEntry` | method | 엔트리 추가/갱신. `kind`는 `"file"` 또는 `"dir"`. 파일이면 `dataBase64`에 Base64 데이터 전달 |
|
|
33
|
+
| `deleteByPrefix` | method | 접두사와 일치하는 모든 엔트리 삭제. 삭제된 항목이 있으면 `true` 반환 |
|
|
34
|
+
| `listChildren` | method | 접두사 바로 아래 자식 목록 반환. 직접 자식만 (재귀적이지 않음) |
|
|
35
|
+
| `ensureDir` | method | 경로의 모든 중간 디렉토리를 재귀적으로 생성. 이미 있으면 건너뜀 |
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
### 최소 예제
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { IndexedDbStore, IndexedDbVirtualFs } from "@simplysm/core-browser";
|
|
43
|
+
|
|
44
|
+
const store = new IndexedDbStore("fsDb", 1, [{ name: "files", keyPath: "path" }]);
|
|
45
|
+
const fs = new IndexedDbVirtualFs(store, "files", "path");
|
|
46
|
+
|
|
47
|
+
await fs.putEntry("/readme.txt", "file", btoa("Hello"));
|
|
48
|
+
const entry = await fs.getEntry("/readme.txt");
|
|
49
|
+
// entry?.kind === "file", entry?.dataBase64 === "SGVsbG8="
|
|
50
|
+
|
|
51
|
+
store.close();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 전형 예제 — 디렉토리 구조 관리
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { IndexedDbStore, IndexedDbVirtualFs } from "@simplysm/core-browser";
|
|
58
|
+
|
|
59
|
+
const store = new IndexedDbStore("appFs", 1, [{ name: "vfs", keyPath: "fullPath" }]);
|
|
60
|
+
const fs = new IndexedDbVirtualFs(store, "vfs", "fullPath");
|
|
61
|
+
|
|
62
|
+
// 중간 디렉토리 자동 생성 (/, /docs 모두 생성됨)
|
|
63
|
+
// fullKeyBuilder는 키를 가공하는 함수 (접두사 추가 등)
|
|
64
|
+
await fs.ensureDir((p) => p, "/docs/reports");
|
|
65
|
+
|
|
66
|
+
// 파일 저장
|
|
67
|
+
await fs.putEntry("/docs/reports/q1.pdf", "file", base64Data);
|
|
68
|
+
|
|
69
|
+
// 자식 목록 조회 (직접 자식만)
|
|
70
|
+
const children = await fs.listChildren("/docs/");
|
|
71
|
+
// [{ name: "reports", isDirectory: true }]
|
|
72
|
+
|
|
73
|
+
// 접두사로 일괄 삭제
|
|
74
|
+
const deleted = await fs.deleteByPrefix("/docs/reports");
|
|
75
|
+
// deleted === true
|
|
76
|
+
|
|
77
|
+
store.close();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 🚫 Anti-patterns
|
|
81
|
+
|
|
82
|
+
### ensureDir 없이 중간 경로의 파일 저장
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// ❌ /docs 디렉토리 엔트리가 없으면 listChildren("/")에서 /docs가 나타나지 않을 수 있음
|
|
86
|
+
await fs.putEntry("/docs/file.txt", "file", data);
|
|
87
|
+
|
|
88
|
+
// ✅ 중간 디렉토리를 먼저 생성
|
|
89
|
+
await fs.ensureDir((p) => p, "/docs");
|
|
90
|
+
await fs.putEntry("/docs/file.txt", "file", data);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**근거**: `putEntry`는 해당 경로의 엔트리만 저장하고 부모 디렉토리를 자동 생성하지 않는다. `listChildren`이 정확한 결과를 반환하려면 중간 디렉토리 엔트리가 존재해야 한다.
|
|
94
|
+
|
|
95
|
+
### prefix에 후행 슬래시 누락
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// ❌ "/docs"로 listChildren하면 "/docsExtra" 같은 형제도 포함될 수 있음
|
|
99
|
+
const children = await fs.listChildren("/docs");
|
|
100
|
+
|
|
101
|
+
// ✅ 후행 슬래시를 포함하여 정확한 디렉토리 자식만 조회
|
|
102
|
+
const children = await fs.listChildren("/docs/");
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**근거**: `listChildren`은 `key.startsWith(prefix)` 후 첫 번째 `/` 세그먼트를 기준으로 자식을 추출한다. 후행 슬래시가 없으면 접두사가 같은 다른 경로가 포함될 수 있다.
|
|
106
|
+
|
|
107
|
+
## Related Types
|
|
108
|
+
|
|
109
|
+
### `VirtualFsEntry`
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
export interface VirtualFsEntry {
|
|
113
|
+
kind: "file" | "dir";
|
|
114
|
+
dataBase64?: string;
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
| Field | Type | Description |
|
|
119
|
+
|-------|------|-------------|
|
|
120
|
+
| `kind` | `"file" \| "dir"` | 엔트리 종류 |
|
|
121
|
+
| `dataBase64` | `string \| undefined` | 파일 데이터 (Base64 인코딩). 디렉토리인 경우 `undefined` |
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# `openFileDialog`
|
|
2
|
+
|
|
3
|
+
프로그래밍 방식으로 파일 선택 대화상자를 여는 함수. `<input type="file">`을 DOM에 추가하지 않고 사용할 수 있다.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- ✅ 버튼 클릭 등 사용자 인터랙션에서 파일 선택이 필요할 때
|
|
8
|
+
- ✅ Angular 컴포넌트에서 `<input type="file">` 없이 파일 선택할 때
|
|
9
|
+
- ❌ 드래그 앤 드롭 파일 업로드 → `dragover`/`drop` 이벤트 직접 처리
|
|
10
|
+
|
|
11
|
+
## Signature
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
export function openFileDialog(options?: {
|
|
15
|
+
accept?: string;
|
|
16
|
+
multiple?: boolean;
|
|
17
|
+
}): Promise<File[] | undefined>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Parameters
|
|
21
|
+
|
|
22
|
+
| Param | Type | Description |
|
|
23
|
+
|-------|------|-------------|
|
|
24
|
+
| `options.accept` | `string` | 파일 형식 필터 (예: `".xlsx,.csv"`, `"image/*"`) |
|
|
25
|
+
| `options.multiple` | `boolean` | 다중 선택 허용 여부. 기본값 `false` |
|
|
26
|
+
|
|
27
|
+
## Returns
|
|
28
|
+
|
|
29
|
+
`Promise<File[] | undefined>` — 파일 선택 시 `File[]`, 취소 시 `undefined`.
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### 최소 예제
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { openFileDialog } from "@simplysm/core-browser";
|
|
37
|
+
|
|
38
|
+
const files = await openFileDialog();
|
|
39
|
+
if (files != null) {
|
|
40
|
+
// 파일 처리
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 전형 예제 — 이미지 다중 선택
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { openFileDialog } from "@simplysm/core-browser";
|
|
48
|
+
|
|
49
|
+
const images = await openFileDialog({
|
|
50
|
+
accept: "image/*",
|
|
51
|
+
multiple: true,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (images != null) {
|
|
55
|
+
for (const file of images) {
|
|
56
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
57
|
+
// 이미지 처리
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|