torch-glare 2.5.5 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/bin/index.js +9 -24
- package/dist/bin/index.js.map +1 -1
- package/dist/src/commands/add.d.ts +2 -2
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +4 -70
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/hook.d.ts +5 -4
- package/dist/src/commands/hook.d.ts.map +1 -1
- package/dist/src/commands/hook.js +7 -75
- package/dist/src/commands/hook.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/layout.d.ts +5 -4
- package/dist/src/commands/layout.d.ts.map +1 -1
- package/dist/src/commands/layout.js +7 -75
- package/dist/src/commands/layout.js.map +1 -1
- package/dist/src/commands/provider.d.ts +5 -4
- package/dist/src/commands/provider.d.ts.map +1 -1
- package/dist/src/commands/provider.js +7 -75
- package/dist/src/commands/provider.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +78 -43
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/utils.d.ts +5 -4
- package/dist/src/commands/utils.d.ts.map +1 -1
- package/dist/src/commands/utils.js +7 -80
- package/dist/src/commands/utils.js.map +1 -1
- package/dist/src/shared/addFromRegistry.d.ts +16 -0
- package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
- package/dist/src/shared/addFromRegistry.js +88 -0
- package/dist/src/shared/addFromRegistry.js.map +1 -0
- package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
- package/dist/src/shared/getInstallCommand.js +5 -0
- package/dist/src/shared/getInstallCommand.js.map +1 -1
- package/dist/src/shared/installDependencies.d.ts +0 -10
- package/dist/src/shared/installDependencies.d.ts.map +1 -1
- package/dist/src/shared/installDependencies.js +0 -17
- package/dist/src/shared/installDependencies.js.map +1 -1
- package/dist/src/shared/installFromPlan.d.ts +7 -5
- package/dist/src/shared/installFromPlan.d.ts.map +1 -1
- package/dist/src/shared/installFromPlan.js +103 -36
- package/dist/src/shared/installFromPlan.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +12 -3
- package/dist/src/shared/loadRegistry.d.ts.map +1 -1
- package/dist/src/shared/loadRegistry.js +19 -20
- package/dist/src/shared/loadRegistry.js.map +1 -1
- package/dist/src/shared/registryClient.d.ts +19 -0
- package/dist/src/shared/registryClient.d.ts.map +1 -0
- package/dist/src/shared/registryClient.js +128 -0
- package/dist/src/shared/registryClient.js.map +1 -0
- package/dist/src/shared/resolveEntry.d.ts +10 -7
- package/dist/src/shared/resolveEntry.d.ts.map +1 -1
- package/dist/src/shared/resolveEntry.js +18 -13
- package/dist/src/shared/resolveEntry.js.map +1 -1
- package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
- package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
- package/dist/src/shared/suggestOtherCommand.js +29 -23
- package/dist/src/shared/suggestOtherCommand.js.map +1 -1
- package/dist/src/types/main.d.ts +31 -2
- package/dist/src/types/main.d.ts.map +1 -1
- package/package.json +6 -11
- package/apps/lib/components/ActionButton.tsx +0 -93
- package/apps/lib/components/ActionsGroup.tsx +0 -27
- package/apps/lib/components/AlertDialog.tsx +0 -204
- package/apps/lib/components/Avatar.tsx +0 -46
- package/apps/lib/components/Badge.tsx +0 -250
- package/apps/lib/components/BadgeField.tsx +0 -338
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -317
- package/apps/lib/components/ButtonGroup.tsx +0 -190
- package/apps/lib/components/Calendar.tsx +0 -115
- package/apps/lib/components/Card.tsx +0 -95
- package/apps/lib/components/Checkbox.tsx +0 -42
- package/apps/lib/components/ColorPicker.tsx +0 -441
- package/apps/lib/components/ConclusionHeader.tsx +0 -148
- package/apps/lib/components/ContextMenu.tsx +0 -571
- package/apps/lib/components/CountBadge.tsx +0 -52
- package/apps/lib/components/DataTable.tsx +0 -213
- package/apps/lib/components/DataViews/badge.ts +0 -49
- package/apps/lib/components/DataViews/cell.tsx +0 -324
- package/apps/lib/components/DataViews/context.ts +0 -144
- package/apps/lib/components/DataViews/data-views.tsx +0 -383
- package/apps/lib/components/DataViews/filters/children.tsx +0 -98
- package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
- package/apps/lib/components/DataViews/filters/index.ts +0 -4
- package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
- package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
- package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
- package/apps/lib/components/DataViews/filters/values.ts +0 -173
- package/apps/lib/components/DataViews/header.tsx +0 -220
- package/apps/lib/components/DataViews/hooks/index.ts +0 -5
- package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
- package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
- package/apps/lib/components/DataViews/index.ts +0 -84
- package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
- package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
- package/apps/lib/components/DataViews/panel/index.ts +0 -3
- package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
- package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
- package/apps/lib/components/DataViews/panel/section.tsx +0 -81
- package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
- package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
- package/apps/lib/components/DataViews/slots.ts +0 -63
- package/apps/lib/components/DataViews/states.tsx +0 -38
- package/apps/lib/components/DataViews/types.ts +0 -510
- package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
- package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
- package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
- package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
- package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
- package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
- package/apps/lib/components/DatePicker.tsx +0 -232
- package/apps/lib/components/Dialog.tsx +0 -116
- package/apps/lib/components/Divider.tsx +0 -28
- package/apps/lib/components/Drawer.tsx +0 -420
- package/apps/lib/components/DropdownMenu.tsx +0 -540
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -73
- package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -163
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -91
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
- package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
- package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
- package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
- package/apps/lib/components/FormBuilder/index.ts +0 -31
- package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
- package/apps/lib/components/FormBuilder/submit.tsx +0 -47
- package/apps/lib/components/FormBuilder/types.ts +0 -311
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -128
- package/apps/lib/components/FormRenderer/detail.tsx +0 -207
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -297
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -15
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -339
- package/apps/lib/components/FormRenderer/types.ts +0 -78
- package/apps/lib/components/FormSummary.tsx +0 -282
- package/apps/lib/components/HeaderBar.tsx +0 -117
- package/apps/lib/components/ImageAttachment.tsx +0 -209
- package/apps/lib/components/InnerLabelField.tsx +0 -154
- package/apps/lib/components/Input.tsx +0 -224
- package/apps/lib/components/InputField.tsx +0 -147
- package/apps/lib/components/InputOTP.tsx +0 -84
- package/apps/lib/components/Label.tsx +0 -129
- package/apps/lib/components/LabelField.tsx +0 -76
- package/apps/lib/components/LabeledCheckBox.tsx +0 -51
- package/apps/lib/components/LabeledRadio.tsx +0 -51
- package/apps/lib/components/LinkButton.tsx +0 -94
- package/apps/lib/components/LoginButton.tsx +0 -51
- package/apps/lib/components/PasswordLevel.tsx +0 -58
- package/apps/lib/components/Popover.tsx +0 -312
- package/apps/lib/components/ProfileMenu.tsx +0 -85
- package/apps/lib/components/Radio.tsx +0 -59
- package/apps/lib/components/RadioCard.tsx +0 -50
- package/apps/lib/components/ScrollArea.tsx +0 -54
- package/apps/lib/components/SearchField.tsx +0 -62
- package/apps/lib/components/SearchableSelect.tsx +0 -318
- package/apps/lib/components/SearchableTable.tsx +0 -344
- package/apps/lib/components/SearchableTree.tsx +0 -485
- package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
- package/apps/lib/components/SectionBlock.tsx +0 -147
- package/apps/lib/components/Select.tsx +0 -347
- package/apps/lib/components/SimpleSelect.tsx +0 -225
- package/apps/lib/components/Skeleton.tsx +0 -12
- package/apps/lib/components/SlideDatePicker.tsx +0 -253
- package/apps/lib/components/SpinLoading.tsx +0 -174
- package/apps/lib/components/Stepper.tsx +0 -480
- package/apps/lib/components/Switch.tsx +0 -82
- package/apps/lib/components/TabFormItem.tsx +0 -153
- package/apps/lib/components/TabSwitch.tsx +0 -172
- package/apps/lib/components/Table.tsx +0 -610
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
- package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
- package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
- package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
- package/apps/lib/components/TextEditor/index.ts +0 -7
- package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
- package/apps/lib/components/Textarea.tsx +0 -117
- package/apps/lib/components/Timeline.tsx +0 -263
- package/apps/lib/components/Toast.tsx +0 -87
- package/apps/lib/components/Toggle.tsx +0 -125
- package/apps/lib/components/ToggleButton.tsx +0 -140
- package/apps/lib/components/Tooltip.tsx +0 -116
- package/apps/lib/components/TransparentLabel.tsx +0 -71
- package/apps/lib/components/TreeDropDown.tsx +0 -115
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
- package/apps/lib/components/TreeFolder/icons.tsx +0 -60
- package/apps/lib/components/TreeFolder/index.ts +0 -24
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
- package/apps/lib/components/TreeFolder/types.ts +0 -77
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
- package/apps/lib/hooks/useActiveTreeItem.ts +0 -58
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
- package/apps/lib/hooks/useIsMobile.ts +0 -21
- package/apps/lib/hooks/useResize.ts +0 -67
- package/apps/lib/hooks/useTagSelection.ts +0 -214
- package/apps/lib/layouts/CNLayout.tsx +0 -372
- package/apps/lib/layouts/DataViewCard.tsx +0 -62
- package/apps/lib/layouts/FieldSection.tsx +0 -91
- package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
- package/apps/lib/providers/ThemeProvider.tsx +0 -84
- package/apps/lib/registry.json +0 -1201
- package/apps/lib/tsconfig.json +0 -9
- package/apps/lib/tsconfig.tsbuildinfo +0 -1
- package/apps/lib/utils/cn.ts +0 -6
- package/apps/lib/utils/color.ts +0 -175
- package/apps/lib/utils/dataViews/path.ts +0 -67
- package/apps/lib/utils/dataViews/query.ts +0 -73
- package/apps/lib/utils/dataViews/types.ts +0 -187
- package/apps/lib/utils/dateFormat.ts +0 -108
- package/apps/lib/utils/resize.ts +0 -31
- package/apps/lib/utils/types.ts +0 -16
- package/docs/BLOCKS.md +0 -129
- package/docs/CHANGELOG-1.1.16.md +0 -108
- package/docs/Cover.png +0 -0
- package/docs/README.md +0 -215
- package/docs/components/action-button.md +0 -638
- package/docs/components/actions-group.md +0 -708
- package/docs/components/alert-dialog.md +0 -920
- package/docs/components/avatar.md +0 -709
- package/docs/components/badge-field.md +0 -712
- package/docs/components/badge.md +0 -301
- package/docs/components/breadcrumb.md +0 -930
- package/docs/components/button-group.md +0 -650
- package/docs/components/button.md +0 -639
- package/docs/components/calendar.md +0 -555
- package/docs/components/card.md +0 -622
- package/docs/components/chart-block-tool.md +0 -129
- package/docs/components/checkbox.md +0 -699
- package/docs/components/cn-layout.md +0 -854
- package/docs/components/color-picker.md +0 -101
- package/docs/components/conclusion-header.md +0 -80
- package/docs/components/context-menu.md +0 -483
- package/docs/components/count-badge.md +0 -560
- package/docs/components/data-table.md +0 -854
- package/docs/components/data-views/backend-response.md +0 -324
- package/docs/components/data-views/examples/a11y-rtl.md +0 -250
- package/docs/components/data-views/examples/api-orders-route.md +0 -130
- package/docs/components/data-views/examples/fields.md +0 -362
- package/docs/components/data-views/examples/filters.md +0 -307
- package/docs/components/data-views/examples/inbox-routing.md +0 -218
- package/docs/components/data-views/examples/index.md +0 -29
- package/docs/components/data-views/examples/overview.md +0 -244
- package/docs/components/data-views/examples/panel.md +0 -212
- package/docs/components/data-views/examples/scale.md +0 -231
- package/docs/components/data-views/examples/server-side.md +0 -210
- package/docs/components/data-views/examples/state.md +0 -250
- package/docs/components/data-views/examples/tree-custom.md +0 -388
- package/docs/components/data-views/examples/view-registry.md +0 -313
- package/docs/components/data-views/examples/views.md +0 -534
- package/docs/components/data-views/guide.md +0 -405
- package/docs/components/data-views/index.md +0 -1495
- package/docs/components/data-views/migration.md +0 -79
- package/docs/components/date-picker.md +0 -857
- package/docs/components/dialog.md +0 -929
- package/docs/components/divider.md +0 -766
- package/docs/components/drawer.md +0 -654
- package/docs/components/dropdown-menu.md +0 -668
- package/docs/components/field-hint.md +0 -898
- package/docs/components/field-section.md +0 -781
- package/docs/components/form-builder.md +0 -276
- package/docs/components/form-renderer.md +0 -326
- package/docs/components/form-summary.md +0 -138
- package/docs/components/form.md +0 -785
- package/docs/components/header-bar.md +0 -188
- package/docs/components/image-attachment.md +0 -906
- package/docs/components/inner-label-field.md +0 -819
- package/docs/components/input-field.md +0 -623
- package/docs/components/input-otp.md +0 -756
- package/docs/components/input.md +0 -634
- package/docs/components/label-field.md +0 -770
- package/docs/components/label.md +0 -761
- package/docs/components/labeled-check-box.md +0 -642
- package/docs/components/labeled-radio.md +0 -796
- package/docs/components/link-button.md +0 -685
- package/docs/components/login-button.md +0 -872
- package/docs/components/password-level.md +0 -803
- package/docs/components/popover.md +0 -649
- package/docs/components/profile-menu.md +0 -656
- package/docs/components/radio-card.md +0 -801
- package/docs/components/radio.md +0 -735
- package/docs/components/scroll-area.md +0 -691
- package/docs/components/search-field.md +0 -702
- package/docs/components/searchable-select.md +0 -368
- package/docs/components/searchable-table.md +0 -438
- package/docs/components/searchable-tree-dialog.md +0 -190
- package/docs/components/searchable-tree.md +0 -200
- package/docs/components/section-block.md +0 -477
- package/docs/components/select.md +0 -709
- package/docs/components/simple-select.md +0 -741
- package/docs/components/skeleton.md +0 -706
- package/docs/components/slide-date-picker.md +0 -837
- package/docs/components/spin-loading.md +0 -696
- package/docs/components/stepper.md +0 -316
- package/docs/components/switch.md +0 -770
- package/docs/components/tab-form-item.md +0 -773
- package/docs/components/tab-switch.md +0 -170
- package/docs/components/table-dnd-wrapper.md +0 -107
- package/docs/components/table.md +0 -1088
- package/docs/components/text-editor.md +0 -735
- package/docs/components/textarea.md +0 -681
- package/docs/components/timeline.md +0 -254
- package/docs/components/toast.md +0 -773
- package/docs/components/toggle-button.md +0 -643
- package/docs/components/toggle.md +0 -882
- package/docs/components/tooltip.md +0 -513
- package/docs/components/transparent-label.md +0 -721
- package/docs/components/tree-drop-down.md +0 -740
- package/docs/components/tree-folder.md +0 -110
- package/docs/components/tree-sub-layout.md +0 -707
- package/docs/explanation/architecture.md +0 -54
- package/docs/explanation/design-system.md +0 -52
- package/docs/how-to/form-and-list-recipes.md +0 -386
- package/docs/how-to/forms-with-form-builder.md +0 -472
- package/docs/how-to/guides.md +0 -1027
- package/docs/migration/changelog.md +0 -54
- package/docs/migration/form-builder-2.5.2.md +0 -113
- package/docs/reference/cli.md +0 -112
- package/docs/reference/components.md +0 -572
- package/docs/reference/hooks.md +0 -1500
- package/docs/reference/providers.md +0 -866
- package/docs/reference/tailwind-plugins.md +0 -942
- package/docs/reference/theme.md +0 -85
- package/docs/reference/types.md +0 -1016
- package/docs/reference/utilities.md +0 -704
- package/docs/tutorials/building-first-form.md +0 -846
- package/docs/tutorials/component-composition.md +0 -882
- package/docs/tutorials/getting-started.md +0 -302
- package/docs/tutorials/theming-basics.md +0 -785
|
@@ -1,66 +1,133 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import { copyComponentsRecursively } from "./copyComponentsRecursively.js";
|
|
5
3
|
import { ensureDirectoryExists } from "./ensureDirectoryExists.js";
|
|
6
4
|
import { installNpmPackages } from "./installDependencies.js";
|
|
7
5
|
import { isInstalled } from "./resolveEntry.js";
|
|
8
6
|
import { loadRegistry } from "./loadRegistry.js";
|
|
7
|
+
import { fetchRegistryItems, RegistryError } from "./registryClient.js";
|
|
9
8
|
import { resolveInstallPlan } from "./resolveInstallPlan.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
/** Where this project's files live — `<cwd>/<glare.json path>`, with a leading "@/" stripped. */
|
|
10
|
+
export function installRoot(config) {
|
|
11
|
+
return path.join(process.cwd(), config.path.replace("@/", ""));
|
|
12
|
+
}
|
|
13
13
|
/**
|
|
14
14
|
* Install one registry item and everything it needs.
|
|
15
15
|
*
|
|
16
|
-
* Dependencies come from
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* Dependencies come from the registry index — the same generated graph the docs and the MCP server
|
|
17
|
+
* read — rather than from scanning import statements as files are written. The old walker had no
|
|
18
|
+
* visited set and no cycle guard, and ran once per copied file, so a 35-file component triggered 35
|
|
19
|
+
* recursive walks; worse, a dependency skipped because its folder already existed was never
|
|
20
20
|
* descended into, which silently truncated the tree (`add DataViews` installed 16 of 55 items and
|
|
21
21
|
* exited 0).
|
|
22
22
|
*
|
|
23
23
|
* Resolving up front also gives `force` a coherent meaning: it applies to **every** item in the
|
|
24
24
|
* plan, not only the one you named.
|
|
25
25
|
*/
|
|
26
|
-
export function installFromPlan(type, name, config, force) {
|
|
27
|
-
const registry = loadRegistry();
|
|
26
|
+
export async function installFromPlan(type, name, config, force) {
|
|
27
|
+
const registry = await loadRegistry();
|
|
28
28
|
const plan = resolveInstallPlan(registry, type, name);
|
|
29
29
|
if (!plan)
|
|
30
30
|
return null;
|
|
31
|
-
const
|
|
31
|
+
const root = installRoot(config);
|
|
32
|
+
// Work out what needs writing before fetching anything — there is no reason to pull 200KB over
|
|
33
|
+
// the network for 55 items only to skip 54 of them as already present.
|
|
34
|
+
const pending = [];
|
|
32
35
|
const skipped = [];
|
|
33
36
|
for (const item of plan.items) {
|
|
34
|
-
|
|
35
|
-
if (!fs.existsSync(source))
|
|
36
|
-
continue;
|
|
37
|
-
const entry = path.basename(item.path);
|
|
38
|
-
const targetDir = path.join(process.cwd(), config.path.replace("@/", ""), item.type);
|
|
39
|
-
if (isInstalled(targetDir, entry) && !force) {
|
|
37
|
+
if (isInstalled(path.join(root, item.type), entryOf(item.path)) && !force) {
|
|
40
38
|
skipped.push(`${item.type}/${item.name}`);
|
|
41
|
-
continue;
|
|
42
39
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
else {
|
|
41
|
+
pending.push(item);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const payloads = pending.length
|
|
45
|
+
? await fetchRegistryItems(pending)
|
|
46
|
+
: new Map();
|
|
47
|
+
const installed = [];
|
|
48
|
+
for (const item of pending) {
|
|
49
|
+
const ref = `${item.type}/${item.name}`;
|
|
50
|
+
const payload = payloads.get(ref);
|
|
51
|
+
if (!payload) {
|
|
52
|
+
// The index listed it, so a gap here means the registry is internally inconsistent.
|
|
53
|
+
// The old code `continue`d past a missing source without a word, which is how a
|
|
54
|
+
// partial install passed for a complete one.
|
|
55
|
+
throw new RegistryError(`${ref} is in the registry index but could not be fetched.`);
|
|
56
|
+
}
|
|
57
|
+
writeItem(payload, item.path, root, force);
|
|
58
|
+
installed.push(ref);
|
|
51
59
|
}
|
|
52
60
|
// Once, for the union — not once per file, which is what produced five "cn.ts has been added"
|
|
53
61
|
// lines and five separate npm invocations for a single `add`.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
return {
|
|
63
|
+
installed,
|
|
64
|
+
skipped,
|
|
65
|
+
npm: installNpmPackages(pinRanges(plan.npmDependencies, payloads, registry)),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve each npm dependency to a spec with its version range attached.
|
|
70
|
+
*
|
|
71
|
+
* Unpinned, `add DataTable` pulled @tanstack/react-table v9 against a component written for v8 —
|
|
72
|
+
* code that could not compile on arrival. Two sources carry the range, and both are consulted:
|
|
73
|
+
* a fetched item payload already has it inlined (`clsx@^2.1.1`), and the index hoists ranges into
|
|
74
|
+
* a shared `npmVersions` map. The payload is preferred because it is the more specific of the two;
|
|
75
|
+
* the index covers items that were skipped and so never fetched.
|
|
76
|
+
*
|
|
77
|
+
* Reading only the index — which is what this did — meant a registry with a sparse `npmVersions`
|
|
78
|
+
* installed everything unpinned in silence, which is the exact failure pinning exists to prevent.
|
|
79
|
+
*/
|
|
80
|
+
function pinRanges(deps, payloads, registry) {
|
|
81
|
+
const fromPayloads = new Map();
|
|
82
|
+
for (const payload of payloads.values()) {
|
|
83
|
+
for (const spec of payload.dependencies ?? []) {
|
|
84
|
+
// The leading `@` of a scoped package is not a separator.
|
|
85
|
+
const at = spec.lastIndexOf("@");
|
|
86
|
+
if (at > 0)
|
|
87
|
+
fromPayloads.set(spec.slice(0, at), spec);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const unpinned = [];
|
|
91
|
+
const specs = [...deps].map((dep) => {
|
|
92
|
+
const fromPayload = fromPayloads.get(dep);
|
|
93
|
+
if (fromPayload)
|
|
94
|
+
return fromPayload;
|
|
95
|
+
const range = registry.npmVersions?.[dep];
|
|
96
|
+
if (range)
|
|
97
|
+
return `${dep}@${range}`;
|
|
98
|
+
unpinned.push(dep);
|
|
99
|
+
return dep;
|
|
61
100
|
});
|
|
62
|
-
|
|
63
|
-
|
|
101
|
+
if (unpinned.length) {
|
|
102
|
+
console.warn(`⚠️ No version range for ${unpinned.join(", ")} — installing the latest. ` +
|
|
103
|
+
`The registry should pin these.`);
|
|
104
|
+
}
|
|
105
|
+
return specs;
|
|
106
|
+
}
|
|
107
|
+
/** The file or folder an item occupies, e.g. `Button.tsx` or `DataViews`, from its registry path. */
|
|
108
|
+
function entryOf(itemPath) {
|
|
109
|
+
return path.basename(itemPath);
|
|
110
|
+
}
|
|
111
|
+
/** Write one payload's files under `root`, replacing what is there when forced. */
|
|
112
|
+
function writeItem(payload, itemPath, root, force) {
|
|
113
|
+
const ref = `${payload.type}/${payload.name}`;
|
|
114
|
+
// Replacing: clear the old copy first, so a folder that lost files upstream does not keep
|
|
115
|
+
// them locally.
|
|
116
|
+
const target = path.join(root, payload.type, entryOf(itemPath));
|
|
117
|
+
if (force && fs.existsSync(target))
|
|
118
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
119
|
+
for (const file of payload.files) {
|
|
120
|
+
const dest = path.join(root, file.target);
|
|
121
|
+
// The target comes off the network, so it is not trusted to stay inside the project.
|
|
122
|
+
// Note there is no `dest !== root` escape hatch: a target of "" or "." normalises to the
|
|
123
|
+
// root itself, which is not a file we should ever write, and letting it through only
|
|
124
|
+
// turned a clear rejection into an EISDIR crash.
|
|
125
|
+
if (!dest.startsWith(root + path.sep)) {
|
|
126
|
+
throw new RegistryError(`${ref} wants to write outside the install directory: ${file.target}`);
|
|
127
|
+
}
|
|
128
|
+
ensureDirectoryExists(path.dirname(dest));
|
|
129
|
+
fs.writeFileSync(dest, file.content);
|
|
130
|
+
}
|
|
64
131
|
}
|
|
65
132
|
/** `✅ 55 installed, 0 skipped` — truncation has to be visible, not inferred from silence. */
|
|
66
133
|
export function reportInstall(name, result, where) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installFromPlan.js","sourceRoot":"","sources":["../../../cli/src/shared/installFromPlan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"installFromPlan.js","sourceRoot":"","sources":["../../../cli/src/shared/installFromPlan.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { Registry } from "../types/main.js";
|
|
2
2
|
/**
|
|
3
|
-
* Load and cache the
|
|
4
|
-
*
|
|
3
|
+
* Load and cache the component registry index.
|
|
4
|
+
*
|
|
5
|
+
* Fetched once per process and handed to `resolveInstallPlan`, which walks dependencies locally
|
|
6
|
+
* rather than recursing over the network per item.
|
|
7
|
+
*
|
|
8
|
+
* There is no local fallback. The CLI used to ship the whole library inside its own tarball and
|
|
9
|
+
* could quietly install from that when the network failed; it no longer carries it, so "the
|
|
10
|
+
* registry is unreachable" is a real failure and is reported as one. Silently succeeding from a
|
|
11
|
+
* stale bundle was how a project ended up with component source nobody could account for.
|
|
5
12
|
*/
|
|
6
|
-
export declare function loadRegistry(): Registry
|
|
13
|
+
export declare function loadRegistry(): Promise<Registry>;
|
|
14
|
+
/** Test seam — the module-level cache would otherwise leak between cases. */
|
|
15
|
+
export declare function resetRegistryCache(): void;
|
|
7
16
|
//# sourceMappingURL=loadRegistry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadRegistry.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/loadRegistry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loadRegistry.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/loadRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAK5C;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAWtD;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = path.dirname(__filename);
|
|
6
|
-
// registry.json ships alongside the library source (apps/lib), the same location the
|
|
7
|
-
// command modules resolve their template dirs from.
|
|
8
|
-
const REGISTRY_PATH = path.resolve(__dirname, "../../../apps/lib/registry.json");
|
|
1
|
+
import { fetchRegistryIndex, indexUrl, RegistryError } from "./registryClient.js";
|
|
9
2
|
let cached = null;
|
|
10
3
|
/**
|
|
11
|
-
* Load and cache the
|
|
12
|
-
*
|
|
4
|
+
* Load and cache the component registry index.
|
|
5
|
+
*
|
|
6
|
+
* Fetched once per process and handed to `resolveInstallPlan`, which walks dependencies locally
|
|
7
|
+
* rather than recursing over the network per item.
|
|
8
|
+
*
|
|
9
|
+
* There is no local fallback. The CLI used to ship the whole library inside its own tarball and
|
|
10
|
+
* could quietly install from that when the network failed; it no longer carries it, so "the
|
|
11
|
+
* registry is unreachable" is a real failure and is reported as one. Silently succeeding from a
|
|
12
|
+
* stale bundle was how a project ended up with component source nobody could account for.
|
|
13
13
|
*/
|
|
14
|
-
export function loadRegistry() {
|
|
14
|
+
export async function loadRegistry() {
|
|
15
15
|
if (cached)
|
|
16
16
|
return cached;
|
|
17
|
-
if (!fs.existsSync(REGISTRY_PATH)) {
|
|
18
|
-
console.error("❌ registry.json not found. It is generated from library source via " +
|
|
19
|
-
"`node scripts/bin/generateRegistry/index.js`.");
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
17
|
try {
|
|
23
|
-
cached =
|
|
24
|
-
return cached;
|
|
18
|
+
cached = await fetchRegistryIndex();
|
|
25
19
|
}
|
|
26
20
|
catch (error) {
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
const reason = error instanceof RegistryError ? error.message : String(error);
|
|
22
|
+
throw new RegistryError(`${reason}\n Registry: ${indexUrl()}`);
|
|
29
23
|
}
|
|
24
|
+
return cached;
|
|
25
|
+
}
|
|
26
|
+
/** Test seam — the module-level cache would otherwise leak between cases. */
|
|
27
|
+
export function resetRegistryCache() {
|
|
28
|
+
cached = null;
|
|
30
29
|
}
|
|
31
30
|
//# sourceMappingURL=loadRegistry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadRegistry.js","sourceRoot":"","sources":["../../../cli/src/shared/loadRegistry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loadRegistry.js","sourceRoot":"","sources":["../../../cli/src/shared/loadRegistry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAElF,IAAI,MAAM,GAAoB,IAAI,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAC9B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,CAAC;QACD,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,KAAK,YAAY,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9E,MAAM,IAAI,aAAa,CAAC,GAAG,MAAM,kBAAkB,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,kBAAkB;IAC9B,MAAM,GAAG,IAAI,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Registry, RegistryItem, RegistryItemPayload } from "../types/main.js";
|
|
2
|
+
export declare class RegistryError extends Error {
|
|
3
|
+
}
|
|
4
|
+
/** Fetch the registry index: every item, its dependencies and its file list, without content. */
|
|
5
|
+
export declare function fetchRegistryIndex(): Promise<Registry>;
|
|
6
|
+
/** The index URL, exported so an error can name it without re-deriving it. */
|
|
7
|
+
export declare function indexUrl(): string;
|
|
8
|
+
/** Test seam, and a guard against one command's fetches leaking into another's. */
|
|
9
|
+
export declare function resetItemMemo(): void;
|
|
10
|
+
/** Fetch one item payload by its absolute URL, memoised and validated. */
|
|
11
|
+
export declare function fetchItemByUrl(url: string): Promise<RegistryItemPayload>;
|
|
12
|
+
/**
|
|
13
|
+
* Fetch every item in an install plan, `CONCURRENCY` at a time.
|
|
14
|
+
*
|
|
15
|
+
* Serially this is the difference between roughly 15s and 2s for `add DataViews`; unbounded it is
|
|
16
|
+
* 55 simultaneous connections, which is how you get rate-limited by a registry host.
|
|
17
|
+
*/
|
|
18
|
+
export declare function fetchRegistryItems(items: RegistryItem[]): Promise<Map<string, RegistryItemPayload>>;
|
|
19
|
+
//# sourceMappingURL=registryClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registryClient.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/registryClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAgCpF,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAmC3C,iGAAiG;AACjG,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,QAAQ,CAAC,CAM5D;AAED,8EAA8E;AAC9E,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAYD,mFAAmF;AACnF,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,0EAA0E;AAC1E,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA4B9E;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACpC,KAAK,EAAE,YAAY,EAAE,GACtB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAa3C"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the hosted component registry.
|
|
3
|
+
*
|
|
4
|
+
* Until 2.5.7 the CLI shipped the whole library inside its own npm tarball and copied from there,
|
|
5
|
+
* which meant a one-line component fix required publishing a new version of the CLI. Components now
|
|
6
|
+
* come from a registry over HTTP, so source and tooling version independently.
|
|
7
|
+
*
|
|
8
|
+
* Everything here is fetch + JSON. `resolveInstallPlan` still does the dependency walk locally
|
|
9
|
+
* against a single fetched index, rather than recursing over the network per item — that keeps the
|
|
10
|
+
* resolver a pure, synchronous, testable function, and turns an N-deep request waterfall into one
|
|
11
|
+
* request plus one parallel batch.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Where components come from: the `registry/` directory on the Glare repo's default branch,
|
|
15
|
+
* served by raw.githubusercontent.com.
|
|
16
|
+
*
|
|
17
|
+
* Fetched straight from the repo rather than through a branded URL on the docs site. The site was
|
|
18
|
+
* proxying this exact origin, and measuring it made the case plain: the proxy was *slower* than
|
|
19
|
+
* what it proxied (0.31-0.67s vs 0.27s), traded a CDN for a single VPS, and coupled every install
|
|
20
|
+
* to a website deploy. raw already sends `access-control-allow-origin: *`, which was the one thing
|
|
21
|
+
* the route added that could not be got for free.
|
|
22
|
+
*/
|
|
23
|
+
const REGISTRY_URL = "https://raw.githubusercontent.com/TORCH-Corp/TORCH-Glare/main/registry";
|
|
24
|
+
/** Parallel item fetches. Measured ~275ms per request; `add DataViews` is 55 items. */
|
|
25
|
+
const CONCURRENCY = 8;
|
|
26
|
+
const REQUEST_TIMEOUT_MS = 20000;
|
|
27
|
+
export class RegistryError extends Error {
|
|
28
|
+
}
|
|
29
|
+
async function getJson(url) {
|
|
30
|
+
let response;
|
|
31
|
+
try {
|
|
32
|
+
response = await fetch(url, {
|
|
33
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
34
|
+
headers: { Accept: "application/json" },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// Offline, DNS failure, timeout. Deliberately distinguished from a 404 below: conflating
|
|
39
|
+
// them sends people hunting for a typo in a component name when the network is at fault.
|
|
40
|
+
throw new RegistryError(`Could not reach the registry at ${url}\n ${error.message}`);
|
|
41
|
+
}
|
|
42
|
+
if (response.status === 404) {
|
|
43
|
+
throw new RegistryError(`Not found in the registry: ${url}`);
|
|
44
|
+
}
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new RegistryError(`Registry returned ${response.status} for ${url}`);
|
|
47
|
+
}
|
|
48
|
+
const body = await response.text();
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(body);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
throw new RegistryError(`Registry returned invalid JSON from ${url} ` +
|
|
54
|
+
`(${body.slice(0, 80).replace(/\s+/g, " ")}…)`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Fetch the registry index: every item, its dependencies and its file list, without content. */
|
|
58
|
+
export async function fetchRegistryIndex() {
|
|
59
|
+
const registry = await getJson(indexUrl());
|
|
60
|
+
if (!registry || !Array.isArray(registry.items)) {
|
|
61
|
+
throw new RegistryError(`Registry index at ${indexUrl()} has no items array.`);
|
|
62
|
+
}
|
|
63
|
+
return registry;
|
|
64
|
+
}
|
|
65
|
+
/** The index URL, exported so an error can name it without re-deriving it. */
|
|
66
|
+
export function indexUrl() {
|
|
67
|
+
return `${REGISTRY_URL}/index.json`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Payloads already fetched in this process, keyed by absolute URL.
|
|
71
|
+
*
|
|
72
|
+
* `update` is what makes this matter. It calls `add` once per installed item, and each call
|
|
73
|
+
* resolves its own dependency closure — which overlap heavily. Measured with 55 items installed:
|
|
74
|
+
* 287 item fetches for 55 distinct items, every one a request the registry host has to serve.
|
|
75
|
+
* With this, 55.
|
|
76
|
+
*/
|
|
77
|
+
const memo = new Map();
|
|
78
|
+
/** Test seam, and a guard against one command's fetches leaking into another's. */
|
|
79
|
+
export function resetItemMemo() {
|
|
80
|
+
memo.clear();
|
|
81
|
+
}
|
|
82
|
+
/** Fetch one item payload by its absolute URL, memoised and validated. */
|
|
83
|
+
export async function fetchItemByUrl(url) {
|
|
84
|
+
const hit = memo.get(url);
|
|
85
|
+
if (hit)
|
|
86
|
+
return hit;
|
|
87
|
+
const pending = (async () => {
|
|
88
|
+
const payload = await getJson(url);
|
|
89
|
+
if (!Array.isArray(payload.files) || payload.files.length === 0) {
|
|
90
|
+
throw new RegistryError(`Registry item at ${url} has no files.`);
|
|
91
|
+
}
|
|
92
|
+
for (const file of payload.files) {
|
|
93
|
+
if (typeof file?.target !== "string" || typeof file?.content !== "string") {
|
|
94
|
+
throw new RegistryError(`Registry item at ${url} has a malformed file entry.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return payload;
|
|
98
|
+
})();
|
|
99
|
+
memo.set(url, pending);
|
|
100
|
+
try {
|
|
101
|
+
return await pending;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
// Do not memoise a failure — a transient network error should not poison the rest of
|
|
105
|
+
// the run, and `update` would otherwise repeat one blip across every remaining item.
|
|
106
|
+
memo.delete(url);
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Fetch every item in an install plan, `CONCURRENCY` at a time.
|
|
112
|
+
*
|
|
113
|
+
* Serially this is the difference between roughly 15s and 2s for `add DataViews`; unbounded it is
|
|
114
|
+
* 55 simultaneous connections, which is how you get rate-limited by a registry host.
|
|
115
|
+
*/
|
|
116
|
+
export async function fetchRegistryItems(items) {
|
|
117
|
+
const out = new Map();
|
|
118
|
+
const queue = [...items];
|
|
119
|
+
const workers = Array.from({ length: Math.min(CONCURRENCY, queue.length) }, async () => {
|
|
120
|
+
for (let next = queue.shift(); next; next = queue.shift()) {
|
|
121
|
+
const url = `${REGISTRY_URL}/${next.type}/${next.name}.json`;
|
|
122
|
+
out.set(`${next.type}/${next.name}`, await fetchItemByUrl(url));
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
await Promise.all(workers);
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=registryClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registryClient.js","sourceRoot":"","sources":["../../../cli/src/shared/registryClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resolve a user-provided name to
|
|
2
|
+
* Resolve a user-provided name to a registry item name.
|
|
3
3
|
*
|
|
4
|
-
* `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* component
|
|
4
|
+
* `available` is now the registry's own list of item names, not a `readdirSync` of a templates
|
|
5
|
+
* directory. That inversion matters: resolution used to be filesystem-first, so a name the local
|
|
6
|
+
* listing did not contain was rejected before the registry was ever consulted — which made every
|
|
7
|
+
* component that exists only in the hosted registry unreachable.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Registry names carry no extension, so a user typing `Button.tsx` (or copying it out of a file
|
|
10
|
+
* tree) has it stripped rather than failing to match.
|
|
11
|
+
*
|
|
12
|
+
* Tries, in order: exact · extension stripped · case-insensitive.
|
|
10
13
|
*/
|
|
11
|
-
export declare function resolveEntry(input: string, available: string[]
|
|
14
|
+
export declare function resolveEntry(input: string, available: string[]): string | null;
|
|
12
15
|
/**
|
|
13
16
|
* Is this item actually installed?
|
|
14
17
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveEntry.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/resolveEntry.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"resolveEntry.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/resolveEntry.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAc9E;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQrE"}
|
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
/**
|
|
4
|
-
* Resolve a user-provided name to
|
|
4
|
+
* Resolve a user-provided name to a registry item name.
|
|
5
5
|
*
|
|
6
|
-
* `
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* component
|
|
6
|
+
* `available` is now the registry's own list of item names, not a `readdirSync` of a templates
|
|
7
|
+
* directory. That inversion matters: resolution used to be filesystem-first, so a name the local
|
|
8
|
+
* listing did not contain was rejected before the registry was ever consulted — which made every
|
|
9
|
+
* component that exists only in the hosted registry unreachable.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Registry names carry no extension, so a user typing `Button.tsx` (or copying it out of a file
|
|
12
|
+
* tree) has it stripped rather than failing to match.
|
|
13
|
+
*
|
|
14
|
+
* Tries, in order: exact · extension stripped · case-insensitive.
|
|
12
15
|
*/
|
|
13
|
-
export function resolveEntry(input, available
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
for (const candidate of [`${input}.tsx`, `${input}.ts`]) {
|
|
16
|
+
export function resolveEntry(input, available) {
|
|
17
|
+
const candidates = [input, input.replace(/\.(tsx|ts)$/, "")];
|
|
18
|
+
for (const candidate of candidates) {
|
|
17
19
|
if (available.includes(candidate))
|
|
18
20
|
return candidate;
|
|
19
21
|
}
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
// `torch-glare add button` should not be a dead end when `Button` is right there.
|
|
23
|
+
for (const candidate of candidates) {
|
|
24
|
+
const match = available.find((name) => name.toLowerCase() === candidate.toLowerCase());
|
|
25
|
+
if (match)
|
|
26
|
+
return match;
|
|
27
|
+
}
|
|
23
28
|
return null;
|
|
24
29
|
}
|
|
25
30
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveEntry.js","sourceRoot":"","sources":["../../../cli/src/shared/resolveEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB
|
|
1
|
+
{"version":3,"file":"resolveEntry.js","sourceRoot":"","sources":["../../../cli/src/shared/resolveEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,SAAmB;IAC3D,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC;IAE7D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACjC,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IACxD,CAAC;IAED,kFAAkF;IAClF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;QACvF,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC5B,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,KAAa;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAEzC,IAAI,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACrC,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC3B,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9D,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACrB,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC3D,CAAC;aAAM,CAAC;YACJ,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import type { Registry, RegistryItem } from "../types/main.js";
|
|
2
|
+
type ItemType = RegistryItem["type"];
|
|
1
3
|
/**
|
|
2
4
|
* A name that is not a component may still be something we ship.
|
|
3
5
|
*
|
|
4
6
|
* `torch-glare add useDragDrop` answering only "Component not found" is technically correct and
|
|
5
7
|
* practically useless — it *is* installable, just by a different command. Look before saying no.
|
|
8
|
+
*
|
|
9
|
+
* Reads the registry index rather than scanning sibling directories in the installed package, so
|
|
10
|
+
* it keeps working once the library stops shipping in the tarball.
|
|
6
11
|
*/
|
|
7
|
-
export declare function suggestOtherCommand(input: string): string | null;
|
|
12
|
+
export declare function suggestOtherCommand(registry: Registry, input: string, exclude: ItemType): string | null;
|
|
13
|
+
export {};
|
|
8
14
|
//# sourceMappingURL=suggestOtherCommand.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggestOtherCommand.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/suggestOtherCommand.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"suggestOtherCommand.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/suggestOtherCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE/D,KAAK,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAWrC;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,QAAQ,GAClB,MAAM,GAAG,IAAI,CA2Bf"}
|
|
@@ -1,33 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
{ dir: "utils", command: "util", label: "utility" },
|
|
10
|
-
{ dir: "layouts", command: "layout", label: "layout" },
|
|
11
|
-
{ dir: "providers", command: "provider", label: "provider" },
|
|
12
|
-
];
|
|
1
|
+
/** Which command installs which type, and what to call it in a sentence. */
|
|
2
|
+
const KINDS = {
|
|
3
|
+
components: { command: "add", label: "component" },
|
|
4
|
+
hooks: { command: "hook", label: "hook" },
|
|
5
|
+
utils: { command: "util", label: "utility" },
|
|
6
|
+
layouts: { command: "layout", label: "layout" },
|
|
7
|
+
providers: { command: "provider", label: "provider" },
|
|
8
|
+
};
|
|
13
9
|
/**
|
|
14
10
|
* A name that is not a component may still be something we ship.
|
|
15
11
|
*
|
|
16
12
|
* `torch-glare add useDragDrop` answering only "Component not found" is technically correct and
|
|
17
13
|
* practically useless — it *is* installable, just by a different command. Look before saying no.
|
|
14
|
+
*
|
|
15
|
+
* Reads the registry index rather than scanning sibling directories in the installed package, so
|
|
16
|
+
* it keeps working once the library stops shipping in the tarball.
|
|
18
17
|
*/
|
|
19
|
-
export function suggestOtherCommand(input) {
|
|
18
|
+
export function suggestOtherCommand(registry, input, exclude) {
|
|
20
19
|
const bare = input.replace(/\.(tsx|ts)$/, "").toLowerCase();
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
const match = registry.items.find((item) => item.type !== exclude && item.name.toLowerCase() === bare);
|
|
21
|
+
if (match) {
|
|
22
|
+
const kind = KINDS[match.type];
|
|
23
|
+
return `"${match.name}" is a ${kind.label} — try \`torch-glare ${kind.command} ${match.name}\`.`;
|
|
24
|
+
}
|
|
25
|
+
// No exact match anywhere: offer the closest names of the type they asked for, which catches
|
|
26
|
+
// the ordinary case of a typo or half-remembered name.
|
|
27
|
+
const near = registry.items
|
|
28
|
+
.filter((item) => item.type === exclude)
|
|
29
|
+
.map((item) => item.name)
|
|
30
|
+
.filter((name) => {
|
|
31
|
+
const lower = name.toLowerCase();
|
|
32
|
+
return lower.includes(bare) || bare.includes(lower);
|
|
33
|
+
})
|
|
34
|
+
.slice(0, 3);
|
|
35
|
+
if (near.length) {
|
|
36
|
+
return `Did you mean: ${near.join(", ")}?`;
|
|
31
37
|
}
|
|
32
38
|
return null;
|
|
33
39
|
}
|