diff --git a/cli/pom.xml b/cli/pom.xml
index 7c007cbf..16158d22 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -101,13 +101,6 @@
4.4.14
-
-
- com.github.javakeyring
- java-keyring
- 1.0.4
-
-
com.vdurmont
diff --git a/cli/src/main/java/ca/weblite/jdeploy/cli/di/JDeployCliModule.java b/cli/src/main/java/ca/weblite/jdeploy/cli/di/JDeployCliModule.java
index 604dce02..69b3f230 100644
--- a/cli/src/main/java/ca/weblite/jdeploy/cli/di/JDeployCliModule.java
+++ b/cli/src/main/java/ca/weblite/jdeploy/cli/di/JDeployCliModule.java
@@ -2,14 +2,10 @@
import ca.weblite.jdeploy.cli.util.CliChatThreadDispatcher;
import ca.weblite.jdeploy.cli.util.CliUiThreadDispatcher;
-import ca.weblite.jdeploy.npm.NpmAccountServiceInterface;
-import ca.weblite.jdeploy.npm.PreferencesNpmAccountService;
import ca.weblite.jdeploy.openai.interop.ChatThreadDispatcher;
import ca.weblite.jdeploy.openai.interop.UiThreadDispatcher;
import ca.weblite.jdeploy.project.service.DefaultProjectLoader;
import ca.weblite.jdeploy.project.service.ProjectLoader;
-import ca.weblite.jdeploy.secure.JavaKeyringPasswordService;
-import ca.weblite.jdeploy.secure.PasswordServiceInterface;
import org.codejargon.feather.Provides;
public class JDeployCliModule {
@@ -29,13 +25,4 @@ public ProjectLoader projectLoader(DefaultProjectLoader impl) {
return impl;
}
- @Provides
- public NpmAccountServiceInterface npmAccountServiceInterface(PreferencesNpmAccountService impl) {
- return impl;
- }
- @Provides
- public PasswordServiceInterface passwordServiceInterface(JavaKeyringPasswordService javaKeyringPasswordService) {
- return javaKeyringPasswordService;
- }
-
}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/EditNpmAccountDialog.java b/cli/src/main/java/ca/weblite/jdeploy/gui/EditNpmAccountDialog.java
deleted file mode 100644
index 876227b8..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/EditNpmAccountDialog.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package ca.weblite.jdeploy.gui;
-
-import ca.weblite.jdeploy.npm.NpmAccountInterface;
-
-import javax.swing.*;
-import java.awt.*;
-
-public class EditNpmAccountDialog extends JDialog {
- private EditNpmAccountPanel editNpmAccountPanel;
- private JButton saveButton;
- private JButton cancelButton;
- public EditNpmAccountDialog(Window parent, NpmAccountInterface account) {
- super(parent);
- // Create the layout
- GroupLayout layout = new GroupLayout(this.getContentPane());
- this.getContentPane().setLayout(layout);
-
- // Create the components
- editNpmAccountPanel = new EditNpmAccountPanel(account);
- saveButton = new JButton("Save");
- cancelButton = new JButton("Cancel");
-
- // Set the layout
- layout.setAutoCreateGaps(true);
- layout.setAutoCreateContainerGaps(true);
-
- layout.setHorizontalGroup(
- layout.createParallelGroup(GroupLayout.Alignment.LEADING)
- .addComponent(editNpmAccountPanel)
- .addGroup(layout.createSequentialGroup()
- .addComponent(saveButton)
- .addComponent(cancelButton)
- )
- );
-
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addComponent(editNpmAccountPanel)
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
- .addComponent(saveButton)
- .addComponent(cancelButton)
- )
- );
- pack();
- }
-
- public JTextField getAccountNameField() {
- return editNpmAccountPanel.getAccountNameField();
- }
-
- public JPasswordField getNpmTokenField() {
- return editNpmAccountPanel.getNpmTokenField();
- }
-
- public JButton getSaveButton() {
- return saveButton;
- }
-
- public JButton getCancelButton() {
- return cancelButton;
- }
-
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/EditNpmAccountPanel.java b/cli/src/main/java/ca/weblite/jdeploy/gui/EditNpmAccountPanel.java
deleted file mode 100644
index 3ececd0f..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/EditNpmAccountPanel.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package ca.weblite.jdeploy.gui;
-
-import ca.weblite.jdeploy.npm.NpmAccount;
-import ca.weblite.jdeploy.npm.NpmAccountInterface;
-
-import javax.swing.*;
-
-public class EditNpmAccountPanel extends JPanel {
- private JTextField accountNameField;
- private JPasswordField npmTokenField;
-
- public EditNpmAccountPanel(NpmAccountInterface account) {
- super();
-
- // Create the layout
- GroupLayout layout = new GroupLayout(this);
- setLayout(layout);
-
- // Create the components
- JLabel accountNameLabel = new JLabel("Account Name");
- accountNameField = new JTextField(30);
-
-
- JLabel npmTokenLabel = new JLabel("NPM Token");
- npmTokenField = new JPasswordField(30);
-
- // Set the account name
- accountNameField.setText(account.getNpmAccountName());
-
- // Set the NPM token
- if (account.getNpmToken() != null) {
- npmTokenField.setText(account.getNpmToken());
- }
-
- // Set the layout
- layout.setAutoCreateGaps(true);
- layout.setAutoCreateContainerGaps(true);
-
- layout.setHorizontalGroup(
- layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
- .addComponent(accountNameLabel)
- .addComponent(npmTokenLabel)
- )
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
- .addComponent(accountNameField)
- .addComponent(npmTokenField)
- )
- );
-
- layout.setVerticalGroup(
- layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
- .addComponent(accountNameLabel)
- .addComponent(accountNameField)
- )
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
- .addComponent(npmTokenLabel)
- .addComponent(npmTokenField)
- )
- );
-
-
- }
-
-
- public JPasswordField getNpmTokenField() {
- return npmTokenField;
- }
-
- public JTextField getAccountNameField() {
- return accountNameField;
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditor.java b/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditor.java
index 9bb6d6fd..a52ad3f5 100644
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditor.java
+++ b/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditor.java
@@ -4,14 +4,12 @@
import ca.weblite.jdeploy.JDeploy;
import ca.weblite.jdeploy.gui.controllers.EditGithubWorkflowController;
import ca.weblite.jdeploy.gui.controllers.GenerateGithubWorkflowController;
-import ca.weblite.jdeploy.gui.controllers.NpmAccountChooserController;
import ca.weblite.jdeploy.gui.controllers.VerifyWebsiteController;
import ca.weblite.jdeploy.gui.tabs.CheerpJSettings;
import ca.weblite.jdeploy.gui.tabs.DetailsPanel;
import ca.weblite.jdeploy.helpers.NPMApplicationHelper;
import ca.weblite.jdeploy.models.NPMApplication;
import ca.weblite.jdeploy.npm.NPM;
-import ca.weblite.jdeploy.npm.NpmAccountServiceInterface;
import ca.weblite.jdeploy.npm.TerminalLoginLauncher;
import ca.weblite.jdeploy.services.ExportIdentityService;
import ca.weblite.jdeploy.services.GithubService;
@@ -20,10 +18,8 @@
import ca.weblite.tools.io.FileUtil;
import ca.weblite.tools.io.MD5;
import com.sun.nio.file.SensitivityWatchEventModifier;
-import io.codeworth.panelmatic.PanelBuilder;
import io.codeworth.panelmatic.PanelMatic;
import io.codeworth.panelmatic.util.Groupings;
-import io.codeworth.panelmatic.util.PanelPostProcessors;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
@@ -42,7 +38,6 @@
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
-import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.*;
@@ -1844,52 +1839,9 @@ private void handleExportIdentity0() throws IOException {
}
private void handlePublish0() throws ValidationException {
- handlePublish0(true);
- }
-
- private void handlePublish0(boolean promptForAccount) throws ValidationException {
-
- if (promptForAccount) {
- final boolean[] accountChosen = {false};
- final boolean[] accountChosenResult = {false};
- final Object lock = new Object();
-
- Runnable runnablePublish = () -> {
- NpmAccountChooserController accountChooserController = new NpmAccountChooserController(
- frame, DIContext.getInstance().getInstance(NpmAccountServiceInterface.class)
- );
-
- accountChooserController.show().thenAccept(account -> {
- if (account == null) {
- accountChosen[0] = true;
- synchronized (lock) {
- lock.notify();
- return;
- }
- }
- context.setNpmToken(account.getNpmToken());
- accountChosen[0] = true;
- accountChosenResult[0] = true;
- synchronized (lock) {
- lock.notify();
- }
- });
-
- };
- SwingUtilities.invokeLater(runnablePublish);
-
- while (!accountChosen[0]) {
- try {
- synchronized (lock) {
- lock.wait(1000);
- }
- } catch (InterruptedException ex) {
- throw new RuntimeException(ex);
- }
- }
- if (!accountChosenResult[0]) {
- return;
- }
+ if (!EventQueue.isDispatchThread()) {
+ // We don't prompt on the dispatch thread because promptForNpmToken blocks
+ context.promptForNpmToken(frame);
}
File absDirectory = packageJSONFile.getAbsoluteFile().getParentFile();
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditorContext.java b/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditorContext.java
index fb7398dc..b5bd9341 100644
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditorContext.java
+++ b/cli/src/main/java/ca/weblite/jdeploy/gui/JDeployProjectEditorContext.java
@@ -3,7 +3,6 @@
import ca.weblite.jdeploy.DIContext;
import ca.weblite.jdeploy.interop.DesktopInterop;
import ca.weblite.jdeploy.interop.FileChooserInterop;
-import ca.weblite.jdeploy.npm.NpmAccountChooserInterface;
import ca.weblite.tools.platform.Platform;
import javax.swing.*;
@@ -70,6 +69,10 @@ public boolean useManagedNode() {
return false;
}
+ public void promptForNpmToken(Object parent) {
+
+ }
+
public void setNpmToken(String npmToken) {
this.npmToken = npmToken;
}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/NpmAccountChooserDialog.java b/cli/src/main/java/ca/weblite/jdeploy/gui/NpmAccountChooserDialog.java
deleted file mode 100644
index 2ad43f77..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/NpmAccountChooserDialog.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package ca.weblite.jdeploy.gui;
-
-import ca.weblite.jdeploy.npm.NpmAccountInterface;
-import org.kordamp.ikonli.material.Material;
-import org.kordamp.ikonli.swing.FontIcon;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.List;
-
-public class NpmAccountChooserDialog extends JDialog {
-
- // For demo, we keep references to some UI controls:
- private final JLabel subtitleLabel;
- private final JButton whyButton;
- private final JPanel accountListPanel;
- private final JButton continueButton;
- private final JButton addAccountButton;
- private final JButton closeButton;
-
- // The currently selected account
- private NpmAccountInterface selectedAccount;
- // The currently selected account button (to highlight)
- private JButton selectedButton;
-
- private final Font headerFont = new Font("SansSerif", Font.BOLD, 18);
- private final Font subHeaderFont = new Font("SansSerif", Font.PLAIN, 14);
-
- // Colors
- private final Color textColor = Color.BLACK;
- private final Color linkColor = new Color(0, 120, 220);
- private final Color selectedBackground = new Color(220, 240, 255);
-
- /**
- * Creates a modal, undecorated dialog.
- */
- public NpmAccountChooserDialog(Frame parent, List accounts) {
- super(parent, true);
- setUndecorated(true);
-
- /*
- * 1) Main content with BorderLayout
- * - We'll use the NORTH region for the close button
- * - The CENTER region for all the main content
- */
- JPanel contentPanel = new JPanel(new BorderLayout());
- contentPanel.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
- setContentPane(contentPanel);
-
- /*
- * 2) Top "close button" panel, aligned to the right
- */
- JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
- northPanel.setOpaque(false);
-
- closeButton = createCloseButton(parent);
- northPanel.add(closeButton);
-
- contentPanel.add(northPanel, BorderLayout.NORTH);
-
- /*
- * 3) Main (center) content. We'll still use a BoxLayout to stack
- * the "npm" title, subtitle, account list, etc.
- */
- JPanel centerPanel = new JPanel();
- centerPanel.setBorder(BorderFactory.createEmptyBorder(20, 30, 20, 30));
- centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
- centerPanel.setOpaque(false);
-
- // Title: "npm", centered
- JLabel titleLabel = new JLabel("npm");
- titleLabel.setFont(headerFont);
- titleLabel.setForeground(textColor);
- titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
- centerPanel.add(titleLabel);
- centerPanel.add(Box.createVerticalStrut(8));
-
- // Subtitle: "Select an account"
- subtitleLabel = new JLabel("Select an account");
- subtitleLabel.setFont(subHeaderFont);
- subtitleLabel.setForeground(textColor);
- subtitleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
- centerPanel.add(subtitleLabel);
- centerPanel.add(Box.createVerticalStrut(15));
-
- // "Why" link
- whyButton = createLinkButton("Why am I being asked to select an account?",
- Material.HELP_OUTLINE, linkColor);
- whyButton.setVisible(false);
- whyButton.setAlignmentX(Component.CENTER_ALIGNMENT);
- centerPanel.add(whyButton);
- centerPanel.add(Box.createVerticalStrut(20));
-
- // Account list
- accountListPanel = new JPanel();
- accountListPanel.setLayout(new BoxLayout(accountListPanel, BoxLayout.Y_AXIS));
- accountListPanel.setOpaque(false);
- accountListPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- for (NpmAccountInterface account : accounts) {
- JButton accountBtn = createAccountButton(account);
- accountListPanel.add(accountBtn);
- accountListPanel.add(Box.createVerticalStrut(10));
- }
- centerPanel.add(accountListPanel);
- centerPanel.add(Box.createVerticalStrut(15));
-
- // "Continue" button
- continueButton = new JButton("Continue");
- continueButton.setEnabled(false);
- continueButton.setAlignmentX(Component.CENTER_ALIGNMENT);
- continueButton.setPreferredSize(new Dimension(120, 35));
- continueButton.addActionListener(e -> dispose());
- centerPanel.add(continueButton);
- centerPanel.add(Box.createVerticalStrut(20));
-
- // "Add a new account"
- addAccountButton = createLinkButton("Add a new account", null, linkColor);
- addAccountButton.setAlignmentX(Component.CENTER_ALIGNMENT);
- centerPanel.add(addAccountButton);
-
- contentPanel.add(centerPanel, BorderLayout.CENTER);
-
- // Final setup
- pack();
- setLocationRelativeTo(parent);
- }
-
- /**
- * Shows the dialog (modal). Returns the selected account, or null if none.
- */
- public NpmAccountInterface showDialog() {
- setVisible(true);
- return selectedAccount;
- }
-
- /**
- * Create a button for each account
- */
- private JButton createAccountButton(NpmAccountInterface account) {
- JButton btn = new JButton(account.getNpmAccountName());
- btn.setBorderPainted(false);
- btn.setFocusPainted(false);
- btn.setContentAreaFilled(false);
-
- btn.setHorizontalAlignment(SwingConstants.LEFT);
- btn.setFont(new Font("SansSerif", Font.PLAIN, 14));
-
- // Account icon
- FontIcon icon = FontIcon.of(Material.ACCOUNT_CIRCLE, 20, textColor);
- btn.setIcon(icon);
-
- // Let it expand horizontally
- btn.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
-
- // On click => select
- btn.addActionListener((ActionEvent e) -> {
- selectedAccount = account;
- continueButton.setEnabled(true);
- setSelectedButton(btn);
- });
-
- return btn;
- }
-
- /**
- * Highlight the newly selected button, unhighlight old one.
- */
- private void setSelectedButton(JButton btn) {
- if (selectedButton != null) {
- selectedButton.setOpaque(false);
- selectedButton.setContentAreaFilled(false);
- selectedButton.repaint();
- }
- selectedButton = btn;
- selectedButton.setOpaque(true);
- selectedButton.setContentAreaFilled(true);
- selectedButton.setBackground(selectedBackground);
- selectedButton.repaint();
- }
-
- /**
- * Create link-styled JButtons.
- */
- private JButton createLinkButton(String text, Material iconType, Color linkColor) {
- JButton linkBtn = new JButton(text);
- linkBtn.setFocusPainted(false);
- linkBtn.setBorderPainted(false);
- linkBtn.setContentAreaFilled(false);
- linkBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
- linkBtn.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- linkBtn.setFont(new Font("SansSerif", Font.PLAIN, 12));
- linkBtn.setForeground(linkColor);
-
- if (iconType != null) {
- FontIcon icon = FontIcon.of(iconType, 16, linkColor);
- linkBtn.setIcon(icon);
- }
-
- // Underline on hover
- linkBtn.addMouseListener(new java.awt.event.MouseAdapter() {
- @Override
- public void mouseEntered(java.awt.event.MouseEvent e) {
- linkBtn.setText("" +
- "" + text + "
");
- }
- @Override
- public void mouseExited(java.awt.event.MouseEvent e) {
- linkBtn.setText(text);
- }
- });
-
- return linkBtn;
- }
-
- /**
- * Creates a "close" (X) button for the top-right (NORTH) region.
- */
- private JButton createCloseButton(Frame parent) {
- JButton closeBtn = new JButton();
- closeBtn.setFocusPainted(false);
- closeBtn.setBorderPainted(false);
- closeBtn.setContentAreaFilled(false);
- closeBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-
- FontIcon closeIcon = FontIcon.of(Material.CLOSE, 18, Color.GRAY);
- closeBtn.setIcon(closeIcon);
-
- // On click => clear selected & dispose
- closeBtn.addActionListener(e -> {
- selectedAccount = null;
- dispose();
- if (parent != null) {
- parent.requestFocus();
- }
- });
- return closeBtn;
- }
-
- // External getters if needed
- public JButton getAddAccountButton() {
- return addAccountButton;
- }
- public JButton getWhyButton() {
- return whyButton;
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/SwingExecutor.java b/cli/src/main/java/ca/weblite/jdeploy/gui/SwingExecutor.java
deleted file mode 100644
index 697ab54a..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/SwingExecutor.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package ca.weblite.jdeploy.gui;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.concurrent.Executor;
-
-public class SwingExecutor implements Executor {
- @Override
- public void execute(Runnable command) {
- if (EventQueue.isDispatchThread()) {
- command.run();
- } else {
- SwingUtilities.invokeLater(command);
- }
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/controllers/EditNpmAccountController.java b/cli/src/main/java/ca/weblite/jdeploy/gui/controllers/EditNpmAccountController.java
deleted file mode 100644
index fac99696..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/controllers/EditNpmAccountController.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package ca.weblite.jdeploy.gui.controllers;
-
-import ca.weblite.jdeploy.gui.EditNpmAccountDialog;
-import ca.weblite.jdeploy.npm.NpmAccount;
-import ca.weblite.jdeploy.npm.NpmAccountInterface;
-import ca.weblite.jdeploy.npm.NpmAccountServiceInterface;
-import ca.weblite.jdeploy.gui.SwingExecutor;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.concurrent.Executor;
-
-public abstract class EditNpmAccountController {
-
- private static final Executor EDT_EXECUTOR = new SwingExecutor();
-
- private final EditNpmAccountDialog dialog;
-
- private final Window parentFrame;
-
- private final NpmAccountServiceInterface npmAccountService;
-
- private NpmAccountInterface newAccount;
-
- public EditNpmAccountController(
- Window parentFrame,
- NpmAccountInterface account,
- NpmAccountServiceInterface npmAccountService
- ) {
- this.parentFrame = parentFrame;
- this.dialog = new EditNpmAccountDialog(parentFrame, account);
- dialog.pack();
- dialog.setLocationRelativeTo(parentFrame);
- this.npmAccountService = npmAccountService;
- setupSaveButton();
- setupCancelButton();
-
- }
-
- public void show() {
-
- dialog.setVisible(true);
- }
-
- protected abstract void afterSave(NpmAccountInterface account);
-
- private NpmAccountInterface getAccount() {
- return new NpmAccount(
- dialog.getAccountNameField().getText(),
- isEmpty(dialog.getNpmTokenField())
- ? null :
- new String(dialog.getNpmTokenField().getPassword())
- );
- }
-
- private boolean isEmpty(JPasswordField field) {
- return field.getPassword().length == 0;
- }
-
- private boolean isAccountValid() {
- return !dialog.getAccountNameField().getText().isEmpty() && !isEmpty(dialog.getNpmTokenField());
- }
-
- private void update() {
- dialog.getSaveButton().setEnabled(isAccountValid());
- }
-
- private void setupSaveButton() {
- dialog.getSaveButton().addActionListener(e -> {
- newAccount = getAccount();
- npmAccountService.saveNpmAccount(newAccount).thenAcceptAsync(result->{
- afterSave(newAccount);
- dialog.dispose();
- parentFrame.requestFocus();
- }, EDT_EXECUTOR).exceptionally(t -> {
- EventQueue.invokeLater(() -> {
- JOptionPane.showMessageDialog(
- dialog,
- "Failed to save account: " + t.getMessage(),
- "Error",
- JOptionPane.ERROR_MESSAGE
- );
- });
- return null;
- });
- });
- }
-
- private void setupCancelButton() {
- dialog.getCancelButton().addActionListener(e -> {
- newAccount = null;
- dialog.dispose();
- parentFrame.requestFocus();
- });
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/gui/controllers/NpmAccountChooserController.java b/cli/src/main/java/ca/weblite/jdeploy/gui/controllers/NpmAccountChooserController.java
deleted file mode 100644
index c9c73ef8..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/gui/controllers/NpmAccountChooserController.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package ca.weblite.jdeploy.gui.controllers;
-
-import ca.weblite.jdeploy.gui.NpmAccountChooserDialog;
-import ca.weblite.jdeploy.gui.SwingExecutor;
-import ca.weblite.jdeploy.npm.NpmAccount;
-import ca.weblite.jdeploy.npm.NpmAccountInterface;
-import ca.weblite.jdeploy.npm.NpmAccountServiceInterface;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-
-public class NpmAccountChooserController {
-
- private static final Executor EDT_EXECUTOR = new SwingExecutor();
-
- private final NpmAccountServiceInterface npmAccountService;
-
- private final Frame parentFrame;
-
- private NpmAccountInterface selectedAccount;
-
- public NpmAccountChooserController(Frame parentFrame, NpmAccountServiceInterface npmAccountService) {
- this.npmAccountService = npmAccountService;
- this.parentFrame = parentFrame;
- }
-
- public CompletableFuture show() {
- return npmAccountService.getNpmAccounts().thenComposeAsync(this::showDialog, EDT_EXECUTOR);
- }
-
- public CompletableFuture showDialog(List accounts) {
- NpmAccountChooserDialog dialog = new NpmAccountChooserDialog(parentFrame, accounts);
- JButton newAccountButton = dialog.getAddAccountButton();
- newAccountButton.addActionListener(evt -> {
- EditNpmAccountController controller = new EditNpmAccountController(
- dialog,
- new NpmAccount("", null),
- npmAccountService
- ) {
- @Override
- protected void afterSave(NpmAccountInterface account) {
- selectedAccount = account;
- dialog.dispose();
- parentFrame.requestFocus();
- }
- };
- controller.show();
-
- });
- NpmAccountInterface sel = dialog.showDialog();
- if (sel != null) {
- selectedAccount = sel;
- }
- if (selectedAccount != null) {
- return npmAccountService.loadNpmAccount(selectedAccount).thenApplyAsync(account -> {
-
- if (account == null) {
- return selectedAccount;
- }
- return account;
- }, EDT_EXECUTOR);
- }
- return CompletableFuture.completedFuture(selectedAccount);
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/npm/AbstractNpmAccountChooser.java b/cli/src/main/java/ca/weblite/jdeploy/npm/AbstractNpmAccountChooser.java
deleted file mode 100644
index c9f6bb5b..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/npm/AbstractNpmAccountChooser.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package ca.weblite.jdeploy.npm;
-
-import java.util.List;
-import java.util.concurrent.Future;
-
-public abstract class AbstractNpmAccountChooser implements NpmAccountChooserInterface{
-
- private final NpmAccountServiceInterface npmAccountService;
-
- public AbstractNpmAccountChooser(NpmAccountServiceInterface npmAccountService) {
- this.npmAccountService = npmAccountService;
- }
-
- public abstract Future selectNpmAccount(List accounts);
-
- public abstract Future createNpmAccount();
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccount.java b/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccount.java
deleted file mode 100644
index ce5a4081..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccount.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package ca.weblite.jdeploy.npm;
-
-public class NpmAccount implements NpmAccountInterface {
-
- private final String npmAccountName;
- private final String npmToken;
-
- public NpmAccount(String npmAccountName, String npmToken){
- this.npmAccountName = npmAccountName;
- this.npmToken = npmToken;
- }
- @Override
- public String getNpmAccountName() {
- return npmAccountName;
- }
-
- @Override
- public String getNpmToken() {
- return npmToken;
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountChooserInterface.java b/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountChooserInterface.java
deleted file mode 100644
index dac7d552..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountChooserInterface.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package ca.weblite.jdeploy.npm;
-
-import java.util.List;
-import java.util.concurrent.Future;
-
-public interface NpmAccountChooserInterface {
- Future selectNpmAccount(List accounts);
- Future createNpmAccount();
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountInterface.java b/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountInterface.java
deleted file mode 100644
index f8da660d..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountInterface.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package ca.weblite.jdeploy.npm;
-
-public interface NpmAccountInterface {
- public String getNpmAccountName();
- public String getNpmToken();
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountServiceInterface.java b/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountServiceInterface.java
deleted file mode 100644
index bc63cbc4..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/npm/NpmAccountServiceInterface.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ca.weblite.jdeploy.npm;
-
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Future;
-
-public interface NpmAccountServiceInterface {
- CompletableFuture> getNpmAccounts();
- CompletableFuture saveNpmAccount(NpmAccountInterface account);
-
- CompletableFuture removeNpmAccount(NpmAccountInterface account);
-
- CompletableFuture loadNpmAccount(NpmAccountInterface accountName);
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/npm/PreferencesNpmAccountService.java b/cli/src/main/java/ca/weblite/jdeploy/npm/PreferencesNpmAccountService.java
deleted file mode 100644
index ac7700ef..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/npm/PreferencesNpmAccountService.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package ca.weblite.jdeploy.npm;
-
-import ca.weblite.jdeploy.secure.PasswordServiceInterface;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-
-@Singleton
-public class PreferencesNpmAccountService implements NpmAccountServiceInterface {
-
- private final PasswordServiceInterface passwordService;
-
- @Inject
- public PreferencesNpmAccountService(PasswordServiceInterface passwordService) {
- this.passwordService = passwordService;
- }
-
- /**
- * We'll store account names in a sub-node of Preferences. For example:
- * preferences root: /ca/weblite/jdeploy/npm/PreferencesNpmAccountService
- *
- * Under this node, we can create a child node "npmAccounts" in which each account name
- * is stored as a key. The key is the account name, and the value is also the account name,
- * so that we can iterate over them in #getNpmAccounts().
- */
- private static final Preferences PREFS =
- Preferences.userNodeForPackage(PreferencesNpmAccountService.class)
- .node("npmAccounts");
-
- @Override
- public CompletableFuture> getNpmAccounts() {
- return CompletableFuture.supplyAsync(() -> {
- List accounts = new ArrayList<>();
- try {
- // Retrieve all keys (each key is an npm account name)
- String[] keys = PREFS.keys();
- for (String accountNameKey : keys) {
- // The stored value for each key might just be the account name itself
- String storedAccountName = PREFS.get(accountNameKey, null);
- if (storedAccountName != null) {
- // The token is not loaded here (null),
- // as per requirement: "getNpmAccounts() should return objects with null for the token."
- NpmAccountInterface account = new NpmAccount(storedAccountName, null);
- accounts.add(account);
- }
- }
- } catch (BackingStoreException e) {
- e.printStackTrace();
- }
- return Collections.unmodifiableList(accounts);
- });
- }
-
- @Override
- public CompletableFuture saveNpmAccount(NpmAccountInterface account) {
- return CompletableFuture.runAsync(() -> {
- // 1. Save only the npmAccountName in preferences
- String accountName = account.getNpmAccountName();
- PREFS.put(accountName, accountName);
-
- // 2. Save the token in the system keychain
- String token = account.getNpmToken();
- if (token != null) {
- passwordService.setPassword(accountName, token.toCharArray()).join();
- }
- });
- }
-
- @Override
- public CompletableFuture removeNpmAccount(NpmAccountInterface account) {
- return CompletableFuture.runAsync(() -> {
- String accountName = account.getNpmAccountName();
-
- // 1. Remove the account from preferences
- PREFS.remove(accountName);
-
- // 2. Remove the keychain entry for the token
- passwordService.removePassword(accountName).join();
- });
- }
-
- @Override
- public CompletableFuture loadNpmAccount(NpmAccountInterface account) {
- return CompletableFuture.supplyAsync(() -> {
- // "loadNpmAccount() should load the token of the given account from the keychain,
- // and return a copy of the provided NpmAccount, but with the token."
-
- String accountName = account.getNpmAccountName();
- // Load the token from the system keychain
- CompletableFuture token = passwordService.getPassword(accountName, "Load NPM token from keychain");
-
- // Return a copy of the provided NpmAccount, but with the token
- return token.thenApply(t -> new NpmAccount(accountName, new String(t)))
- .join();
- });
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/secure/JavaKeyringPasswordService.java b/cli/src/main/java/ca/weblite/jdeploy/secure/JavaKeyringPasswordService.java
deleted file mode 100644
index 27b4be54..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/secure/JavaKeyringPasswordService.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package ca.weblite.jdeploy.secure;
-
-import com.github.javakeyring.BackendNotSupportedException;
-import com.github.javakeyring.Keyring;
-import com.github.javakeyring.PasswordAccessException;
-
-import javax.inject.Singleton;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * An implementation of PasswordServiceInterface that uses the cross-platform
- * java-keyring library to store/retrieve/remove passwords on Windows
- * (via Windows Credential Manager), macOS Keychain, or Linux keyrings.
- */
-@Singleton
-public class JavaKeyringPasswordService implements PasswordServiceInterface {
-
- // This is the "service name" or "application ID" used for storing credentials.
- // You can choose any string; it simply labels your credentials in the keyring.
- private static final String SERVICE_NAME = "com.jdeploy";
-
- @Override
- public CompletableFuture getPassword(String name, String prompt) {
- return CompletableFuture.supplyAsync(() -> {
- try {
- // The prompt parameter is ignored in this example,
- // but you could use it to display a UI message if desired.
-
- Keyring keyring = Keyring.create();
- // Retrieve the password associated with (service=SERVICE_NAME, account=name).
- String password = keyring.getPassword(SERVICE_NAME, name);
- // Return as char[] if present, or null if not found.
- return password != null ? password.toCharArray() : null;
- } catch (PasswordAccessException e) {
- throw new RuntimeException(e);
- } catch (BackendNotSupportedException e) {
- throw new RuntimeException(e);
- }
- });
- }
-
- @Override
- public CompletableFuture setPassword(String name, char[] password) {
- return CompletableFuture.runAsync(() -> {
- try {
- Keyring keyring = Keyring.create();
- // Convert the char[] to a String for storing in the keyring
- String passStr = password != null ? new String(password) : null;
-
- // If password is null or empty, you might remove the credential instead.
- if (passStr == null || passStr.isEmpty()) {
- keyring.deletePassword(SERVICE_NAME, name);
- } else {
- // Store the password for (service=SERVICE_NAME, account=name).
- keyring.setPassword(SERVICE_NAME, name, passStr);
- }
-
- // Optionally, overwrite the passStr memory if you want to reduce its exposure
- // but keep in mind Java strings are immutable. You might do more rigorous scrubbing.
- } catch (BackendNotSupportedException e) {
- throw new RuntimeException("Error setting password in keyring", e);
- } catch (PasswordAccessException e) {
- throw new RuntimeException(e);
- }
- });
- }
-
- @Override
- public CompletableFuture removePassword(String name) {
- return CompletableFuture.runAsync(() -> {
- try {
- Keyring keyring = Keyring.create();
- // Removes the credential from the keyring if it exists
- keyring.deletePassword(SERVICE_NAME, name);
- } catch (BackendNotSupportedException e) {
- throw new RuntimeException("Error removing password from keyring", e);
- } catch (PasswordAccessException e) {
- throw new RuntimeException(e);
- }
- });
- }
-}
diff --git a/cli/src/main/java/ca/weblite/jdeploy/secure/PasswordServiceInterface.java b/cli/src/main/java/ca/weblite/jdeploy/secure/PasswordServiceInterface.java
deleted file mode 100644
index 819667c4..00000000
--- a/cli/src/main/java/ca/weblite/jdeploy/secure/PasswordServiceInterface.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package ca.weblite.jdeploy.secure;
-
-import java.util.concurrent.CompletableFuture;
-
-public interface PasswordServiceInterface {
- CompletableFuture getPassword(String name, String prompt);
- CompletableFuture setPassword(String name, char[] password);
-
- CompletableFuture removePassword(String name);
-}