medusa-plugin-order-notes 0.1.2

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.
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@medusajs/framework/utils");
4
+ (0, utils_1.loadEnv)(process.env.NODE_ENV || 'development', process.cwd());
5
+ module.exports = (0, utils_1.defineConfig)({
6
+ projectConfig: {
7
+ redisUrl: process.env.REDIS_URL,
8
+ databaseUrl: process.env.DATABASE_URL,
9
+ http: {
10
+ storeCors: process.env.STORE_CORS || 'http://localhost:5173',
11
+ adminCors: process.env.ADMIN_CORS || 'http://localhost:5173,http://localhost:9000',
12
+ authCors: process.env.AUTH_CORS || 'http://localhost:5173,http://localhost:9000',
13
+ jwtSecret: process.env.JWT_SECRET || 'supersecret',
14
+ cookieSecret: process.env.COOKIE_SECRET || 'supersecret'
15
+ }
16
+ },
17
+ modules: [
18
+ {
19
+ resolve: './src/modules/order-note'
20
+ }
21
+ ]
22
+ });
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVkdXNhLWNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL21lZHVzYS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBaUU7QUFFakUsSUFBQSxlQUFPLEVBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUksYUFBYSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO0FBRTdELE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBQSxvQkFBWSxFQUFDO0lBQzdCLGFBQWEsRUFBRTtRQUNkLFFBQVEsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVM7UUFDL0IsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWTtRQUNyQyxJQUFJLEVBQUU7WUFDTCxTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksdUJBQXVCO1lBQzVELFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSw2Q0FBNkM7WUFDbEYsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxJQUFJLDZDQUE2QztZQUNoRixTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksYUFBYTtZQUNsRCxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksYUFBYTtTQUN4RDtLQUNEO0lBQ0QsT0FBTyxFQUFFO1FBQ1I7WUFDQyxPQUFPLEVBQUUsMEJBQTBCO1NBQ25DO0tBQ0Q7Q0FDRCxDQUFDLENBQUEifQ==
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const react = require("react");
4
+ const adminSdk = require("@medusajs/admin-sdk");
5
+ const ui = require("@medusajs/ui");
6
+ const icons = require("@medusajs/icons");
7
+ const reactQuery = require("@tanstack/react-query");
8
+ const Medusa = require("@medusajs/js-sdk");
9
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
10
+ const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
11
+ const sdk = new Medusa__default.default({
12
+ baseUrl: "/",
13
+ debug: false,
14
+ auth: {
15
+ type: "session"
16
+ }
17
+ });
18
+ const useOrderNotes = (orderId) => {
19
+ return reactQuery.useQuery({
20
+ queryFn: () => sdk.client.fetch("/admin/order-notes", {
21
+ query: { order_id: orderId, limit: 50 }
22
+ }),
23
+ queryKey: ["order-notes", orderId],
24
+ enabled: !!orderId
25
+ });
26
+ };
27
+ const useCreateOrderNote = (orderId) => {
28
+ const queryClient = reactQuery.useQueryClient();
29
+ return reactQuery.useMutation({
30
+ mutationFn: (body) => sdk.client.fetch("/admin/order-notes", { method: "POST", body }),
31
+ onSuccess: () => {
32
+ queryClient.invalidateQueries({ queryKey: ["order-notes", orderId] });
33
+ queryClient.invalidateQueries({ queryKey: ["orders"] });
34
+ queryClient.invalidateQueries({ queryKey: ["order", orderId] });
35
+ }
36
+ });
37
+ };
38
+ const useDeleteOrderNote = (orderId) => {
39
+ const queryClient = reactQuery.useQueryClient();
40
+ return reactQuery.useMutation({
41
+ mutationFn: (id) => sdk.client.fetch(`/admin/order-notes/${id}`, { method: "DELETE" }),
42
+ onSuccess: () => {
43
+ queryClient.invalidateQueries({ queryKey: ["order-notes", orderId] });
44
+ }
45
+ });
46
+ };
47
+ adminSdk.defineWidgetConfig({
48
+ zone: "order.details.after"
49
+ });
50
+ const OrderNotesWidget = ({ data: order }) => {
51
+ const [showForm, setShowForm] = react.useState(false);
52
+ const [noteText, setNoteText] = react.useState("");
53
+ const [sendToCustomer, setSendToCustomer] = react.useState(false);
54
+ const { data: notesData, isLoading } = useOrderNotes(order.id);
55
+ const createMutation = useCreateOrderNote(order.id);
56
+ const deleteMutation = useDeleteOrderNote(order.id);
57
+ const notes = (notesData == null ? void 0 : notesData.order_notes) ?? [];
58
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
59
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
60
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Order Notes" }),
61
+ /* @__PURE__ */ jsxRuntime.jsx(
62
+ ui.Button,
63
+ {
64
+ size: "small",
65
+ variant: "secondary",
66
+ onClick: () => {
67
+ setShowForm((prev) => !prev);
68
+ setNoteText("");
69
+ setSendToCustomer(false);
70
+ },
71
+ children: showForm ? "Cancel" : "Add Note"
72
+ }
73
+ )
74
+ ] }),
75
+ showForm && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 px-6 py-4", children: [
76
+ /* @__PURE__ */ jsxRuntime.jsx(
77
+ ui.Textarea,
78
+ {
79
+ placeholder: "Write a note...",
80
+ value: noteText,
81
+ onChange: (e) => setNoteText(e.target.value),
82
+ rows: 3
83
+ }
84
+ ),
85
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
86
+ /* @__PURE__ */ jsxRuntime.jsx(
87
+ ui.Checkbox,
88
+ {
89
+ id: "send-to-customer",
90
+ checked: sendToCustomer,
91
+ onCheckedChange: (checked) => setSendToCustomer(checked === true)
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "send-to-customer", className: "cursor-pointer", children: "Send to customer" })
95
+ ] }),
96
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
97
+ ui.Button,
98
+ {
99
+ size: "small",
100
+ disabled: !noteText.trim() || createMutation.isPending,
101
+ isLoading: createMutation.isPending,
102
+ onClick: () => createMutation.mutate(
103
+ { order_id: order.id, note: noteText, sent: sendToCustomer },
104
+ {
105
+ onSuccess: () => {
106
+ setNoteText("");
107
+ setSendToCustomer(false);
108
+ setShowForm(false);
109
+ ui.toast.success(sendToCustomer ? "Note added and sent to customer" : "Note added");
110
+ },
111
+ onError: () => ui.toast.error("Failed to add note")
112
+ }
113
+ ),
114
+ children: "Save"
115
+ }
116
+ ) })
117
+ ] }),
118
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Loading..." }) }) : notes.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No notes for this order." }) }) : notes.map((note) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 px-6 py-4", children: [
119
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 flex-1 min-w-0", children: [
120
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "whitespace-pre-wrap break-words", children: note.note }),
121
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-1", children: [
122
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: new Date(note.created_at).toLocaleString() }),
123
+ note.sent && /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "xsmall", color: "blue", children: "Sent to customer" })
124
+ ] })
125
+ ] }),
126
+ /* @__PURE__ */ jsxRuntime.jsx(
127
+ "button",
128
+ {
129
+ className: "text-ui-fg-muted hover:text-ui-fg-base flex-shrink-0 mt-0.5",
130
+ onClick: () => deleteMutation.mutate(note.id, {
131
+ onSuccess: () => ui.toast.success("Note deleted"),
132
+ onError: () => ui.toast.error("Failed to delete note")
133
+ }),
134
+ "aria-label": "Delete note",
135
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "h-4 w-4" })
136
+ }
137
+ )
138
+ ] }, note.id))
139
+ ] });
140
+ };
141
+ const widgetModule = { widgets: [
142
+ {
143
+ Component: OrderNotesWidget,
144
+ zone: ["order.details.after"]
145
+ }
146
+ ] };
147
+ const routeModule = {
148
+ routes: []
149
+ };
150
+ const menuItemModule = {
151
+ menuItems: []
152
+ };
153
+ const formModule = { customFields: {} };
154
+ const displayModule = {
155
+ displays: {}
156
+ };
157
+ const i18nModule = { resources: {} };
158
+ const plugin = {
159
+ widgetModule,
160
+ routeModule,
161
+ menuItemModule,
162
+ formModule,
163
+ displayModule,
164
+ i18nModule
165
+ };
166
+ module.exports = plugin;
@@ -0,0 +1,165 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { defineWidgetConfig } from "@medusajs/admin-sdk";
4
+ import { Container, Heading, Button, Textarea, Checkbox, Label, toast, Text, Badge } from "@medusajs/ui";
5
+ import { Trash } from "@medusajs/icons";
6
+ import { useQuery, useQueryClient, useMutation } from "@tanstack/react-query";
7
+ import Medusa from "@medusajs/js-sdk";
8
+ const sdk = new Medusa({
9
+ baseUrl: "/",
10
+ debug: false,
11
+ auth: {
12
+ type: "session"
13
+ }
14
+ });
15
+ const useOrderNotes = (orderId) => {
16
+ return useQuery({
17
+ queryFn: () => sdk.client.fetch("/admin/order-notes", {
18
+ query: { order_id: orderId, limit: 50 }
19
+ }),
20
+ queryKey: ["order-notes", orderId],
21
+ enabled: !!orderId
22
+ });
23
+ };
24
+ const useCreateOrderNote = (orderId) => {
25
+ const queryClient = useQueryClient();
26
+ return useMutation({
27
+ mutationFn: (body) => sdk.client.fetch("/admin/order-notes", { method: "POST", body }),
28
+ onSuccess: () => {
29
+ queryClient.invalidateQueries({ queryKey: ["order-notes", orderId] });
30
+ queryClient.invalidateQueries({ queryKey: ["orders"] });
31
+ queryClient.invalidateQueries({ queryKey: ["order", orderId] });
32
+ }
33
+ });
34
+ };
35
+ const useDeleteOrderNote = (orderId) => {
36
+ const queryClient = useQueryClient();
37
+ return useMutation({
38
+ mutationFn: (id) => sdk.client.fetch(`/admin/order-notes/${id}`, { method: "DELETE" }),
39
+ onSuccess: () => {
40
+ queryClient.invalidateQueries({ queryKey: ["order-notes", orderId] });
41
+ }
42
+ });
43
+ };
44
+ defineWidgetConfig({
45
+ zone: "order.details.after"
46
+ });
47
+ const OrderNotesWidget = ({ data: order }) => {
48
+ const [showForm, setShowForm] = useState(false);
49
+ const [noteText, setNoteText] = useState("");
50
+ const [sendToCustomer, setSendToCustomer] = useState(false);
51
+ const { data: notesData, isLoading } = useOrderNotes(order.id);
52
+ const createMutation = useCreateOrderNote(order.id);
53
+ const deleteMutation = useDeleteOrderNote(order.id);
54
+ const notes = (notesData == null ? void 0 : notesData.order_notes) ?? [];
55
+ return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
56
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
57
+ /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Order Notes" }),
58
+ /* @__PURE__ */ jsx(
59
+ Button,
60
+ {
61
+ size: "small",
62
+ variant: "secondary",
63
+ onClick: () => {
64
+ setShowForm((prev) => !prev);
65
+ setNoteText("");
66
+ setSendToCustomer(false);
67
+ },
68
+ children: showForm ? "Cancel" : "Add Note"
69
+ }
70
+ )
71
+ ] }),
72
+ showForm && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 px-6 py-4", children: [
73
+ /* @__PURE__ */ jsx(
74
+ Textarea,
75
+ {
76
+ placeholder: "Write a note...",
77
+ value: noteText,
78
+ onChange: (e) => setNoteText(e.target.value),
79
+ rows: 3
80
+ }
81
+ ),
82
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
83
+ /* @__PURE__ */ jsx(
84
+ Checkbox,
85
+ {
86
+ id: "send-to-customer",
87
+ checked: sendToCustomer,
88
+ onCheckedChange: (checked) => setSendToCustomer(checked === true)
89
+ }
90
+ ),
91
+ /* @__PURE__ */ jsx(Label, { htmlFor: "send-to-customer", className: "cursor-pointer", children: "Send to customer" })
92
+ ] }),
93
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
94
+ Button,
95
+ {
96
+ size: "small",
97
+ disabled: !noteText.trim() || createMutation.isPending,
98
+ isLoading: createMutation.isPending,
99
+ onClick: () => createMutation.mutate(
100
+ { order_id: order.id, note: noteText, sent: sendToCustomer },
101
+ {
102
+ onSuccess: () => {
103
+ setNoteText("");
104
+ setSendToCustomer(false);
105
+ setShowForm(false);
106
+ toast.success(sendToCustomer ? "Note added and sent to customer" : "Note added");
107
+ },
108
+ onError: () => toast.error("Failed to add note")
109
+ }
110
+ ),
111
+ children: "Save"
112
+ }
113
+ ) })
114
+ ] }),
115
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Loading..." }) }) : notes.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No notes for this order." }) }) : notes.map((note) => /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 px-6 py-4", children: [
116
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 flex-1 min-w-0", children: [
117
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "whitespace-pre-wrap break-words", children: note.note }),
118
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1", children: [
119
+ /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: new Date(note.created_at).toLocaleString() }),
120
+ note.sent && /* @__PURE__ */ jsx(Badge, { size: "xsmall", color: "blue", children: "Sent to customer" })
121
+ ] })
122
+ ] }),
123
+ /* @__PURE__ */ jsx(
124
+ "button",
125
+ {
126
+ className: "text-ui-fg-muted hover:text-ui-fg-base flex-shrink-0 mt-0.5",
127
+ onClick: () => deleteMutation.mutate(note.id, {
128
+ onSuccess: () => toast.success("Note deleted"),
129
+ onError: () => toast.error("Failed to delete note")
130
+ }),
131
+ "aria-label": "Delete note",
132
+ children: /* @__PURE__ */ jsx(Trash, { className: "h-4 w-4" })
133
+ }
134
+ )
135
+ ] }, note.id))
136
+ ] });
137
+ };
138
+ const widgetModule = { widgets: [
139
+ {
140
+ Component: OrderNotesWidget,
141
+ zone: ["order.details.after"]
142
+ }
143
+ ] };
144
+ const routeModule = {
145
+ routes: []
146
+ };
147
+ const menuItemModule = {
148
+ menuItems: []
149
+ };
150
+ const formModule = { customFields: {} };
151
+ const displayModule = {
152
+ displays: {}
153
+ };
154
+ const i18nModule = { resources: {} };
155
+ const plugin = {
156
+ widgetModule,
157
+ routeModule,
158
+ menuItemModule,
159
+ formModule,
160
+ displayModule,
161
+ i18nModule
162
+ };
163
+ export {
164
+ plugin as default
165
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DELETE = void 0;
4
+ const order_note_1 = require("../../../../modules/order-note");
5
+ const DELETE = async (req, res) => {
6
+ const { id } = req.params;
7
+ const orderNoteService = req.scope.resolve(order_note_1.ORDER_NOTE_MODULE);
8
+ await orderNoteService.deleteOrderNotes([id]);
9
+ res.json({ deleted: [id] });
10
+ };
11
+ exports.DELETE = DELETE;
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29yZGVyLW5vdGVzL1tpZF0vcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsK0RBQWtFO0FBRzNELE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxHQUErQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRixNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQTtJQUN6QixNQUFNLGdCQUFnQixHQUFxQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyw4QkFBaUIsQ0FBQyxDQUFBO0lBQy9FLE1BQU0sZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQzdDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUE7QUFDNUIsQ0FBQyxDQUFBO0FBTFksUUFBQSxNQUFNLFVBS2xCIn0=
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = exports.GET = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const order_note_1 = require("../../../modules/order-note");
6
+ const GET = async (req, res) => {
7
+ const { order_id } = req.validatedQuery;
8
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
9
+ const { data: order_notes, metadata } = await query.graph({
10
+ entity: 'order_note',
11
+ ...req.queryConfig,
12
+ filters: {
13
+ ...(order_id ? { order_id } : {})
14
+ }
15
+ });
16
+ res.json({
17
+ order_notes,
18
+ count: metadata?.count,
19
+ limit: metadata?.take,
20
+ offset: metadata?.skip
21
+ });
22
+ };
23
+ exports.GET = GET;
24
+ const POST = async (req, res) => {
25
+ const orderNoteService = req.scope.resolve(order_note_1.ORDER_NOTE_MODULE);
26
+ const order_note = await orderNoteService.createNote({
27
+ ...req.validatedBody,
28
+ user_id: req.auth_context.actor_id
29
+ });
30
+ res.status(201).json({ order_note });
31
+ };
32
+ exports.POST = POST;
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29yZGVyLW5vdGVzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFEQUFxRTtBQUVyRSw0REFBK0Q7QUFHeEQsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUN2QixHQUF1RCxFQUN2RCxHQUFtQixFQUNsQixFQUFFO0lBQ0gsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLEdBQUcsQ0FBQyxjQUFjLENBQUE7SUFDdkMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFaEUsTUFBTSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3pELE1BQU0sRUFBRSxZQUFZO1FBQ3BCLEdBQUcsR0FBRyxDQUFDLFdBQVc7UUFDbEIsT0FBTyxFQUFFO1lBQ1IsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ2pDO0tBQ0QsQ0FBQyxDQUFBO0lBRUYsR0FBRyxDQUFDLElBQUksQ0FBQztRQUNSLFdBQVc7UUFDWCxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUs7UUFDdEIsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJO1FBQ3JCLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSTtLQUN0QixDQUFDLENBQUE7QUFDSCxDQUFDLENBQUE7QUFyQlksUUFBQSxHQUFHLE9BcUJmO0FBRU0sTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUN4QixHQUF5RCxFQUN6RCxHQUFtQixFQUNsQixFQUFFO0lBQ0gsTUFBTSxnQkFBZ0IsR0FBcUIsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsOEJBQWlCLENBQUMsQ0FBQTtJQUMvRSxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFVBQVUsQ0FBQztRQUNwRCxHQUFHLEdBQUcsQ0FBQyxhQUFhO1FBQ3BCLE9BQU8sRUFBRSxHQUFHLENBQUMsWUFBWSxDQUFDLFFBQVE7S0FDbEMsQ0FBQyxDQUFBO0lBQ0YsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFBO0FBQ3JDLENBQUMsQ0FBQTtBQVZZLFFBQUEsSUFBSSxRQVVoQiJ9
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const http_1 = require("@medusajs/framework/http");
4
+ const validators_1 = require("./validators");
5
+ exports.default = (0, http_1.defineMiddlewares)([
6
+ {
7
+ matcher: '/admin/order-notes',
8
+ method: ['GET'],
9
+ middlewares: [
10
+ (0, http_1.validateAndTransformQuery)(validators_1.AdminGetOrderNotes, {
11
+ defaults: ['id', 'order_id', 'user_id', 'note', 'sent', 'created_at', 'updated_at'],
12
+ isList: true,
13
+ defaultLimit: 20
14
+ })
15
+ ]
16
+ },
17
+ {
18
+ matcher: '/admin/order-notes',
19
+ method: ['POST'],
20
+ middlewares: [(0, http_1.validateAndTransformBody)(validators_1.AdminCreateOrderNote)]
21
+ }
22
+ ]);
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbURBQWlIO0FBQ2pILDZDQUF1RTtBQUV2RSxrQkFBZSxJQUFBLHdCQUFpQixFQUFDO0lBQ2hDO1FBQ0MsT0FBTyxFQUFFLG9CQUFvQjtRQUM3QixNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDZixXQUFXLEVBQUU7WUFDWixJQUFBLGdDQUF5QixFQUFDLCtCQUFrQixFQUFFO2dCQUM3QyxRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxZQUFZLENBQUM7Z0JBQ25GLE1BQU0sRUFBRSxJQUFJO2dCQUNaLFlBQVksRUFBRSxFQUFFO2FBQ2hCLENBQUM7U0FDRjtLQUNEO0lBQ0Q7UUFDQyxPQUFPLEVBQUUsb0JBQW9CO1FBQzdCLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQztRQUNoQixXQUFXLEVBQUUsQ0FBQyxJQUFBLCtCQUF3QixFQUFDLGlDQUFvQixDQUFDLENBQUM7S0FDN0Q7Q0FDRCxDQUFDLENBQUEifQ==
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AdminCreateOrderNote = exports.AdminGetOrderNotes = void 0;
4
+ const zod_1 = require("@medusajs/framework/zod");
5
+ const validators_1 = require("@medusajs/medusa/api/utils/validators");
6
+ exports.AdminGetOrderNotes = (0, validators_1.createFindParams)({
7
+ limit: 20,
8
+ offset: 0
9
+ }).extend({
10
+ order_id: zod_1.z.string().optional()
11
+ });
12
+ exports.AdminCreateOrderNote = zod_1.z.object({
13
+ order_id: zod_1.z.string(),
14
+ note: zod_1.z.string(),
15
+ sent: zod_1.z.boolean().default(false),
16
+ metadata: zod_1.z.record(zod_1.z.unknown()).nullable().optional()
17
+ });
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcGkvdmFsaWRhdG9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpREFBMkM7QUFDM0Msc0VBQXdFO0FBRTNELFFBQUEsa0JBQWtCLEdBQUcsSUFBQSw2QkFBZ0IsRUFBQztJQUNsRCxLQUFLLEVBQUUsRUFBRTtJQUNULE1BQU0sRUFBRSxDQUFDO0NBQ1QsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNULFFBQVEsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFO0NBQy9CLENBQUMsQ0FBQTtBQUdXLFFBQUEsb0JBQW9CLEdBQUcsT0FBQyxDQUFDLE1BQU0sQ0FBQztJQUM1QyxRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRTtJQUNwQixJQUFJLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRTtJQUNoQixJQUFJLEVBQUUsT0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7SUFDaEMsUUFBUSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUMsT0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxFQUFFO0NBQ3JELENBQUMsQ0FBQSJ9
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const order_1 = __importDefault(require("@medusajs/medusa/order"));
8
+ const order_note_1 = __importDefault(require("../modules/order-note"));
9
+ exports.default = (0, utils_1.defineLink)({
10
+ linkable: order_note_1.default.linkable.orderNote,
11
+ field: 'order_id'
12
+ }, order_1.default.linkable.order, {
13
+ readOnly: true
14
+ });
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXItbm90ZS1vcmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saW5rcy9vcmRlci1ub3RlLW9yZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscURBQXNEO0FBQ3RELG1FQUFnRDtBQUNoRCx1RUFBbUQ7QUFFbkQsa0JBQWUsSUFBQSxrQkFBVSxFQUN4QjtJQUNDLFFBQVEsRUFBRSxvQkFBZSxDQUFDLFFBQVEsQ0FBQyxTQUFTO0lBQzVDLEtBQUssRUFBRSxVQUFVO0NBQ2pCLEVBQ0QsZUFBVyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQzFCO0lBQ0MsUUFBUSxFQUFFLElBQUk7Q0FDZCxDQUNELENBQUEifQ==
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const order_1 = __importDefault(require("@medusajs/medusa/order"));
8
+ const order_note_1 = __importDefault(require("../modules/order-note"));
9
+ exports.default = (0, utils_1.defineLink)({
10
+ linkable: order_1.default.linkable.order,
11
+ field: 'id'
12
+ }, {
13
+ ...order_note_1.default.linkable.orderNote.id,
14
+ primaryKey: 'order_id'
15
+ }, {
16
+ readOnly: true
17
+ });
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXItb3JkZXItbm90ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saW5rcy9vcmRlci1vcmRlci1ub3RlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscURBQXNEO0FBQ3RELG1FQUFnRDtBQUNoRCx1RUFBbUQ7QUFFbkQsa0JBQWUsSUFBQSxrQkFBVSxFQUN4QjtJQUNDLFFBQVEsRUFBRSxlQUFXLENBQUMsUUFBUSxDQUFDLEtBQUs7SUFDcEMsS0FBSyxFQUFFLElBQUk7Q0FDWCxFQUNEO0lBQ0MsR0FBRyxvQkFBZSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRTtJQUN4QyxVQUFVLEVBQUUsVUFBVTtDQUN0QixFQUNEO0lBQ0MsUUFBUSxFQUFFLElBQUk7Q0FDZCxDQUNELENBQUEifQ==
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ORDER_NOTE_MODULE = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const service_1 = require("./service");
6
+ exports.ORDER_NOTE_MODULE = 'order_note';
7
+ exports.default = (0, utils_1.Module)(exports.ORDER_NOTE_MODULE, {
8
+ service: service_1.OrderNoteService
9
+ });
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9vcmRlci1ub3RlL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFEQUFrRDtBQUNsRCx1Q0FBNEM7QUFFL0IsUUFBQSxpQkFBaUIsR0FBRyxZQUFZLENBQUE7QUFFN0Msa0JBQWUsSUFBQSxjQUFNLEVBQUMseUJBQWlCLEVBQUU7SUFDeEMsT0FBTyxFQUFFLDBCQUFnQjtDQUN6QixDQUFDLENBQUEifQ==
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Migration20260409171812 = void 0;
4
+ const migrations_1 = require("@medusajs/framework/mikro-orm/migrations");
5
+ class Migration20260409171812 extends migrations_1.Migration {
6
+ async up() {
7
+ this.addSql(`create table if not exists "order_note" ("id" text not null, "order_id" text not null, "user_id" text not null, "note" text not null, "sent" boolean not null default false, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "order_note_pkey" primary key ("id"));`);
8
+ this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_order_note_deleted_at" ON "order_note" ("deleted_at") WHERE deleted_at IS NULL;`);
9
+ }
10
+ async down() {
11
+ this.addSql(`drop table if exists "order_note" cascade;`);
12
+ }
13
+ }
14
+ exports.Migration20260409171812 = Migration20260409171812;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNjA0MDkxNzE4MTIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9vcmRlci1ub3RlL21pZ3JhdGlvbnMvTWlncmF0aW9uMjAyNjA0MDkxNzE4MTIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEseUVBQXFFO0FBRXJFLE1BQWEsdUJBQXdCLFNBQVEsc0JBQVM7SUFFM0MsS0FBSyxDQUFDLEVBQUU7UUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLHdYQUF3WCxDQUFDLENBQUM7UUFDdFksSUFBSSxDQUFDLE1BQU0sQ0FBQyxpSEFBaUgsQ0FBQyxDQUFDO0lBQ2pJLENBQUM7SUFFUSxLQUFLLENBQUMsSUFBSTtRQUNqQixJQUFJLENBQUMsTUFBTSxDQUFDLDRDQUE0QyxDQUFDLENBQUM7SUFDNUQsQ0FBQztDQUVGO0FBWEQsMERBV0MifQ==
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OrderNote = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ exports.OrderNote = utils_1.model.define('order_note', {
6
+ id: utils_1.model.id().primaryKey(),
7
+ order_id: utils_1.model.text(),
8
+ user_id: utils_1.model.text(),
9
+ note: utils_1.model.text(),
10
+ sent: utils_1.model.boolean().default(false),
11
+ metadata: utils_1.model.json().nullable()
12
+ });
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXItbm90ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL29yZGVyLW5vdGUvbW9kZWxzL29yZGVyLW5vdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQWlEO0FBRXBDLFFBQUEsU0FBUyxHQUFHLGFBQUssQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFO0lBQ25ELEVBQUUsRUFBRSxhQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxFQUFFO0lBQzNCLFFBQVEsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFO0lBQ3RCLE9BQU8sRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFO0lBQ3JCLElBQUksRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFO0lBQ2xCLElBQUksRUFBRSxhQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztJQUNwQyxRQUFRLEVBQUUsYUFBSyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRTtDQUNqQyxDQUFDLENBQUEifQ==
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OrderNoteService = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const order_note_1 = require("./models/order-note");
6
+ class OrderNoteService extends (0, utils_1.MedusaService)({ OrderNote: order_note_1.OrderNote }) {
7
+ constructor({ logger, event_bus }, _options) {
8
+ super(...arguments);
9
+ this.logger_ = logger;
10
+ this.eventBusService_ = event_bus;
11
+ }
12
+ async createNote(data) {
13
+ const orderNote = await this.createOrderNotes(data);
14
+ await this.eventBusService_.emit({
15
+ name: 'order-note.created',
16
+ data: { id: orderNote.id }
17
+ });
18
+ this.logger_.info(`Order note created: ${orderNote.id} (sent: ${data.sent})`);
19
+ return orderNote;
20
+ }
21
+ }
22
+ exports.OrderNoteService = OrderNoteService;
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL29yZGVyLW5vdGUvc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxREFBeUQ7QUFDekQsb0RBQStDO0FBSS9DLE1BQWEsZ0JBQWlCLFNBQVEsSUFBQSxxQkFBYSxFQUFDLEVBQUUsU0FBUyxFQUFULHNCQUFTLEVBQUUsQ0FBQztJQUlqRSxZQUNDLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBbUQsRUFDdEUsUUFBYztRQUVkLEtBQUssQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFBO1FBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFBO1FBQ3JCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxTQUFTLENBQUE7SUFDbEMsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVLENBQUMsSUFNaEI7UUFDQSxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUVuRCxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7WUFDaEMsSUFBSSxFQUFFLG9CQUFvQjtZQUMxQixJQUFJLEVBQUUsRUFBRSxFQUFFLEVBQUUsU0FBUyxDQUFDLEVBQUUsRUFBRTtTQUMxQixDQUFDLENBQUE7UUFFRixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyx1QkFBdUIsU0FBUyxDQUFDLEVBQUUsV0FBVyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQTtRQUU3RSxPQUFPLFNBQVMsQ0FBQTtJQUNqQixDQUFDO0NBQ0Q7QUEvQkQsNENBK0JDIn0=
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Lacey Pevey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # medusa-plugin-order-notes
2
+
3
+ Order notes plugin adding Medusa v1-style notes for Medusa v2. Add internal notes to orders and optionally send them to customers via email.
4
+
5
+ [Documentation](https://pevey.com/medusa-plugin-order-notes)
6
+
7
+ If you are not familiar with Medusa, you can learn more on [the project web site](https://www.medusajs.com/).
8
+
9
+ ## Features
10
+
11
+ - Add notes to any order from the Order detail page
12
+ - Option to mark notes as "sent to customer" for email notification
13
+ - Widget on Order detail page displaying all notes with timestamps
14
+ - Delete notes when no longer needed
15
+ - Filterable by order ID via the admin API
16
+
17
+ ## Installation
18
+
19
+ Inside your medusa backend root folder:
20
+
21
+ ```bash
22
+ yarn add medusa-plugin-order-notes
23
+ ```
24
+
25
+ Replace "yarn add" with the correct command for your package manager if you are using (for example) npm, pnpm, or bun.
26
+
27
+ ## Configuration
28
+
29
+ Enable in your `medusa-config.ts` file. Example:
30
+
31
+ ```ts
32
+ module.exports = defineConfig({
33
+ //... other config
34
+ plugins: [
35
+ {
36
+ resolve: 'medusa-plugin-order-notes',
37
+ options: {}
38
+ }
39
+ // ... other plugins
40
+ ]
41
+ })
42
+ ```
43
+
44
+ To ensure order notes cannot be queried in GET requests to the API, add 'order_note' to your restricted fields in `medusa-config.ts`.
45
+
46
+ ```ts
47
+ module.exports = defineConfig({
48
+ projectConfig: {
49
+ // ... other settings
50
+ http: {
51
+ // ... other settings
52
+ restrictedFields: {
53
+ store: ['order_note']
54
+ }
55
+ }
56
+ }
57
+ })
58
+ ```
59
+
60
+ ## Usage
61
+
62
+ - Navigate to any Order detail page in the Medusa admin.
63
+ - Use the Order Notes widget to add, view, and delete notes.
64
+ - Check "Send to customer" when creating a note to trigger an email notification.
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "medusa-plugin-order-notes",
3
+ "version": "0.1.2",
4
+ "description": "Order notes plugin adding Medusa v1-style notes for Medusa v2",
5
+ "author": "Lacey Pevey",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/pevey/medusa-plugins"
10
+ },
11
+ "homepage": "https://pevey.com/medusa-plugin-order-notes",
12
+ "files": [
13
+ ".medusa/server"
14
+ ],
15
+ "exports": {
16
+ "./package.json": "./package.json",
17
+ "./admin": {
18
+ "import": "./.medusa/server/src/admin/index.mjs",
19
+ "require": "./.medusa/server/src/admin/index.js",
20
+ "default": "./.medusa/server/src/admin/index.js"
21
+ },
22
+ "./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
23
+ "./modules/*": "./.medusa/server/src/modules/*/index.js",
24
+ "./providers/*": "./.medusa/server/src/providers/*/index.js",
25
+ "./*": "./.medusa/server/src/*.js",
26
+ ".": "./.medusa/server/src/modules/order-note/index.js"
27
+ },
28
+ "keywords": [
29
+ "medusa-v2",
30
+ "medusa",
31
+ "order notes",
32
+ "notes"
33
+ ],
34
+ "scripts": {
35
+ "build": "medusa plugin:build",
36
+ "clean:snapshots": "find . -name '.snapshot-*.json' -path '*/migrations/*' -delete",
37
+ "dev": "medusa plugin:develop",
38
+ "prepublishOnly": "medusa plugin:build",
39
+ "test:unit": "TEST_TYPE=unit NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --detectOpenHandles --forceExit --passWithNoTests",
40
+ "test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --detectOpenHandles --forceExit"
41
+ },
42
+ "devDependencies": {
43
+ "@medusajs/admin-sdk": "2.13.6",
44
+ "@medusajs/cli": "2.13.6",
45
+ "@medusajs/framework": "2.13.6",
46
+ "@medusajs/icons": "2.13.6",
47
+ "@medusajs/js-sdk": "2.13.6",
48
+ "@medusajs/medusa": "2.13.6",
49
+ "@medusajs/test-utils": "2.13.6",
50
+ "@medusajs/ui": "4.0.25",
51
+ "@swc/core": "^1.7.28",
52
+ "@swc/jest": "^0.2.39",
53
+ "@types/jest": "^30.0.0",
54
+ "@types/node": "^20.0.0",
55
+ "@types/react": "^18.3.2",
56
+ "@types/react-dom": "^18.2.25",
57
+ "jest": "^29.7.0",
58
+ "prop-types": "^15.8.1",
59
+ "react": "^18.2.0",
60
+ "react-dom": "^18.2.0",
61
+ "ts-node": "^10.9.2",
62
+ "typescript": "^5.6.2",
63
+ "vite": "^5.2.11",
64
+ "yalc": "^1.0.0-pre.53"
65
+ },
66
+ "peerDependencies": {
67
+ "@medusajs/admin-sdk": "2.13.6",
68
+ "@medusajs/cli": "2.13.6",
69
+ "@medusajs/framework": "2.13.6",
70
+ "@medusajs/icons": "2.13.6",
71
+ "@medusajs/medusa": "2.13.6",
72
+ "@medusajs/test-utils": "2.13.6",
73
+ "@medusajs/ui": "4.0.25"
74
+ },
75
+ "engines": {
76
+ "node": ">=20"
77
+ }
78
+ }