Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(adapters): Add Drizzle #587

Merged

Conversation

notrab
Copy link
Contributor

@notrab notrab commented Jan 18, 2024

WHY are these changes introduced?

Drizzle is popular TypeScript ORM that would benefit Shopify App developers.

WHAT is this pull request doing?

This PR adds the ability to use Drizzle as your storage adapter.

Some things aren't clear from a Drizzle side (it doesn't look to be possible or similar to Prisma). There doesn't appear to be a way that I can find in the Drizzle docs to get the schema from a db instance so that's why the constructor requires 2 args — db and sessions.

I tested this using a local SQLite file (via libSQL) and Drizzle following the documentation in the README.md.

If there are any changes or things incorrect, please let me know.

Type of change

  • Minor: New feature (non-breaking change which adds functionality)

Checklist

  • I have used yarn changeset to create a draft changelog entry (do NOT update the CHANGELOG.md files manually)
  • I have added/updated tests for this change
  • I have documented new APIs/updated the documentation for modified APIs (for public APIs)

@notrab notrab requested a review from a team as a code owner January 18, 2024 13:56
@matteodepalo
Copy link
Contributor

Hi @notrab, thank you for your contribution! We're reviewing this internally and we'll get back to you as soon as we can.

@notrab
Copy link
Contributor Author

notrab commented Jan 18, 2024

Awesome, thanks @matteodepalo. I'm new to using Drizzle but happy to change anything, just let me know.

@blanklob
Copy link

This will close #560

@realmikesolo
Copy link
Contributor

Hello, @notrab and @matteodepalo . I am an active contributor to Drizzle ORM and have some improvements that I'd like to implement for this adapter. These include enhancing type-safety and optimizing SQL operations for better correctness and performance, which I believe will make them more suitable for Drizzle ORM. I suggest we postpone this pull request until I have made these improvements based on this code. What are your thoughts on this?

@notrab
Copy link
Contributor Author

notrab commented Jan 18, 2024

@realmikesolo that would be awesome! We asked a few questions in Discord yesterday but didn't get far, I'd love your help!

I'll get you added to the tursodatabase fork as a contributor! ❤️

@realmikesolo
Copy link
Contributor

realmikesolo commented Jan 18, 2024

@notrab, thank you! I'm starting to work on this. For any questions or discussions, you can contact me on Discord at @strattt.

@notrab
Copy link
Contributor Author

notrab commented Jan 18, 2024

@realmikesolo sounds good! It’s probably easier you fork and PR the branch. I’ll ping you on Discord.

@realmikesolo
Copy link
Contributor

I have signed the CLA!

@notrab
Copy link
Contributor Author

notrab commented Jan 22, 2024

Hey @matteodepalo, with these changes by @realmikesolo we should be good to continue in the review process ❤️

@paulomarg
Copy link
Contributor

Hey folks, thank you for contributing! I'll spend some time digging into this, but on the surface it makes sense to me. One thing I notice is that we don't seem to have any tests yet.

We provide a battery of tests that are shared across all of our adapters (e.g. for SQLite or for PGSQL). We use podman to spin up a postgres container, and then run the batteryOfTests to ensure that all of the adapters are consistently implementing SessionStorage.

You should be able to run that if you run yarn build at the top level to build the test utils that provide the battery of tests.

Please let me know if you have any issues adding the tests, and in the meantime I'll go through the code, though I don't expect I'll have too much to say there :)

* add: drizzle adapters for pg & sqlite;
update: readme;

* fixes according to review
@realmikesolo
Copy link
Contributor

Hi, @paulomarg. I am trying to run tests, but have encountered an issue that jest cannot process ES module syntax, as it seems to be using default configuration parameters. Could you provide more details on how to set up the test workflow to allow Jest to properly handle ES module code?

@notrab
Copy link
Contributor Author

notrab commented Feb 13, 2024

@paulomarg I just cloned main and that has failing tests for me too 🤔

 FAIL  packages/shopify-app-express/src/middlewares/__tests__/ensure-installed-on-shop.test.ts
  ● Test suite failed to run

    TypeError: Cannot read properties of undefined (reading 'enableGlobally')

      at jestAdapter (../../node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:36:25)

This was also updated a few days ago:

"@shopify/shopify-app-session-storage-memory": "^3.0.0",

Not sure if it could be related with that package versioning.

I have merged main into this branch and push the dep version update to "@shopify/shopify-app-session-storage-test-utils": "^2.0.0" that was made to other packages a few days about by the github-bot.

@realmikesolo and I would appreciate any help getting whatever failing tests resolved. I tried to revert the changes to the loom config to see if it was that tripping up tests but I get the same result.

@paulomarg
Copy link
Contributor

paulomarg commented Feb 13, 2024

@paulomarg I just cloned main and that has failing tests for me too 🤔

That's so weird! I just created a PR and it worked just fine, including CI, so this isn't happening every time. I wonder if this could be because of the node version you're running? I've tried it with node 18 and 20 myself.

Also, could this be it? jestjs/jest#13259 (comment) - it sounds like the versions of jest and jest-circus need to be aligned.

@notrab
Copy link
Contributor Author

notrab commented Feb 13, 2024

@paulomarg ive merged the latest changes @realmikesolo and I were discussing regarding Prisma and main test fixes. This also includes a MySQL adapter.

@notrab
Copy link
Contributor Author

notrab commented Feb 19, 2024

Hey @paulomarg, I just wanted to follow up to see if there was anything you could do to help us get this over the line?

@realmikesolo and I both have inconsistent tests passing with main as well as this branch.

@paulomarg
Copy link
Contributor

Hey! I played around with this error a bit, and strangely I don't get it on main - but I was able to get it to work (not 100% reliably, unfortunately) by adding resolutions for the jest and jest-circus packages to the root dir's package.json file. I'd be OK with that as a solution but I haven't found the silver bullet yet :(

@paulomarg
Copy link
Contributor

Quick update: this seems to work for me, I got the tests to pass reliably by adding this to the root package.json:

@@ -26,6 +26,7 @@
     "eslint": "^8.55.0",
     "eslint-plugin-prettier": "^5.1.3",
     "jest": "^29.1.0",
+    "jest-environment-jsdom": "^29.7.0",
     "jest-fetch-mock": "^3.0.3",
     "jest-runner-eslint": "^2.1.2",
     "prettier": "^3.2.4",
@@ -34,6 +35,11 @@
     "tslib": "^2.6.2",
     "typescript": "5.3.3"
   },
+  "resolutions": {
+    "jest": "^29.1.0",
+    "jest-circus": "^29.1.0",
+    "ts-jest": "^29.1.0"
+  },
   "dependencies": {},
   "workspaces": [
     "packages/*"

@notrab
Copy link
Contributor Author

notrab commented Feb 22, 2024

Quick update: this seems to work for me, I got the tests to pass reliably by adding this to the root package.json:

@@ -26,6 +26,7 @@
     "eslint": "^8.55.0",
     "eslint-plugin-prettier": "^5.1.3",
     "jest": "^29.1.0",
+    "jest-environment-jsdom": "^29.7.0",
     "jest-fetch-mock": "^3.0.3",
     "jest-runner-eslint": "^2.1.2",
     "prettier": "^3.2.4",
@@ -34,6 +35,11 @@
     "tslib": "^2.6.2",
     "typescript": "5.3.3"
   },
+  "resolutions": {
+    "jest": "^29.1.0",
+    "jest-circus": "^29.1.0",
+    "ts-jest": "^29.1.0"
+  },
   "dependencies": {},
   "workspaces": [
     "packages/*"

That's great @paulomarg! Do you want to commit that or should I?

@paulomarg
Copy link
Contributor

Would you mind doing it and running locally to see if that fixes it for you? That should tell us whether it'll work in CI :)

@notrab
Copy link
Contributor Author

notrab commented Feb 22, 2024

Even more errors on the branch when those are added 🙈

CleanShot 2024-02-22 at 14 22 08@2x

Here are the errors on main:

We'll commit the resolutions to this branch so you can see if they fail.

@notrab
Copy link
Contributor Author

notrab commented Feb 23, 2024

Hey @paulomarg

I've tried with multiple engineers on our side to run the tests locally (with and without the resolutions) and it still fails on main. It could be related to this issue though.

Also, I noticed that loom config is using node 16 and there's a message from GitHub Actions that this isn't supported. If there's any changes to be made there, I can merge any changes you make on that.

@paulomarg
Copy link
Contributor

paulomarg commented Feb 23, 2024

I ended up running into a similar issue here: #626

I believe I have it fixed in a way that will make CI happy, including passing @web3-storage through babel. Hopefully that will fix your issue too if you rebase once we merge 🙏

Might cause a couple of conflicts in your loom config - you should just have to add the drizzle one.

Also, I noticed that loom config is using node 16 and there's a message from GitHub Actions that this isn't supported

We'll be moving away from node 16 in the future, but for now there's no need to change that, thank you!

@notrab
Copy link
Contributor Author

notrab commented Feb 24, 2024

Hey @paulomarg @realmikesolo

I've merged upstream and all tests are passing.

* add: mysql adapter & update: tests

* merge upstream

* bump shopify packages for drizzle
Copy link
Contributor

@paulomarg paulomarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this out in an app and it worked like a charm! The tests are passing, but we had a few linting errors, could you please fix those so we can merge?

Also: 🎉

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, something just occurred to me while checking this out: the code for all the adapters seems to be very similar.

I may have asked this before, but is there no way to have a generic type for the db param that we can share across all of the adapters, so we only need to implement them once? Probably ok if there's no easy way to do that, but it would make this adapter easier to maintain in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, we can't create a generic type for the db parameter with Drizzle, but I think I can create a function that will return the proper adapter based on the type of the db parameter. Something like this:

export function createSessionStorage(params: Params) {
  if (is(params.db, BaseSQLiteDatabase)) {
    return new DrizzleSessionStorageSQLite(
      params.db,
      params.sessionTable as SQLiteSessionTable,
    );
  } else if (is(params.db, MySqlDatabase)) {
    return new DrizzleSessionStorageMySQL(
      params.db,
      params.sessionTable as MySQLSessionTable,
    );
  } else if (is(params.db, PgDatabase)) {
    return new DrizzleSessionStoragePostgres(
      params.db,
      params.sessionTable as PostgresSessionTable,
    );
  }
}

export type Params =
  | {
      db: BaseSQLiteDatabase<'sync' | 'async', any, any>;
      sessionTable: SQLiteSessionTable;
    }
  | {
      db: MySqlDatabase<MySQLQueryResultHKT, PreparedQueryHKTBase, any>;
      sessionTable: MySQLSessionTable;
    }
  | {
      db: PgDatabase<PostgresQueryResultHKT, any>;
      sessionTable: PostgresSessionTable;
    };
const storage = createSessionStorage({
  db: drizzleDb,
  sessionTable,
});

const shopify = shopifyApp({
  sessionStorage: storage,
  // ...
});

Would this be suitable, or should we just leave it as it is now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think that might end up complicating things a bit more. We can re-evaluate to see if people are running into problems with the way things are now.

@notrab
Copy link
Contributor Author

notrab commented Feb 26, 2024

@paulomarg lint errors resolved. I think there was a reason db wasn't a generic but I'll leave that to @realmikesolo to better answer.

PS. Thanks for all your time reviewing and making this PR a reality! Same for @realmikesolo 🥳

Copy link
Contributor

@paulomarg paulomarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to say big thanks to @realmikesolo and @notrab for sticking with this and seeing it through.

Hopefully this package will be helpful to folks who prefer to work with Drizzle when they're writing apps!

@realmikesolo
Copy link
Contributor

@paulomarg @notrab Thank you very much for your cooperation! It was a pleasure to work on this package with you! 🥳

@paulomarg paulomarg merged commit 4053132 into Shopify:main Feb 26, 2024
6 checks passed
@notrab notrab deleted the shopify-app-session-storage-drizzle branch February 27, 2024 12:13
@notrab
Copy link
Contributor Author

notrab commented Feb 27, 2024

@paulomarg is there a timeline for when this will be published to NPM? We'd love to blog about this and link to the package.

Thanks 🙏🏻

@paulomarg
Copy link
Contributor

It will be included in the next release. We don't have a fixed scheduled but we try to release at least every couple of weeks.

@blanklob
Copy link

blanklob commented Mar 8, 2024

Keep us updated when this merged and ready for use.

@paulomarg
Copy link
Contributor

Hey folks, we just published v1 of the Drizzle package 🎉

Please let us know if you have any issues using it!

@blanklob
Copy link

Now all we need is a new docker file to deploy remix app with Drizzle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants