feat: Add an analytics module and local and posthog providers (#12505)
* feat: Add an analytics module and local and posthog providers * fix: Add tests and wire up in missing places * fix: Address feedback and add missing module typing * fix: Address feedback and add missing module typing --------- Co-authored-by: Adrien de Peretti <adrien.deperetti@gmail.com> Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
49 files changed
+1009
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
import { Link } from "@medusajs/modules-sdk"
|
import { Link } from "@medusajs/modules-sdk"
|
||||||
import {
|
import {
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
|
IAnalyticsModuleService,
|
||||||
IApiKeyModuleService,
|
IApiKeyModuleService,
|
||||||
IAuthModuleService,
|
IAuthModuleService,
|
||||||
ICacheService,
|
ICacheService,
|
||||||
@@ -48,6 +49,7 @@ declare module "@medusajs/types" {
|
|||||||
[ContainerRegistrationKeys.REMOTE_QUERY]: RemoteQueryFunction
|
[ContainerRegistrationKeys.REMOTE_QUERY]: RemoteQueryFunction
|
||||||
[ContainerRegistrationKeys.QUERY]: Omit<RemoteQueryFunction, symbol>
|
[ContainerRegistrationKeys.QUERY]: Omit<RemoteQueryFunction, symbol>
|
||||||
[ContainerRegistrationKeys.LOGGER]: Logger
|
[ContainerRegistrationKeys.LOGGER]: Logger
|
||||||
|
[Modules.ANALYTICS]: IAnalyticsModuleService
|
||||||
[Modules.AUTH]: IAuthModuleService
|
[Modules.AUTH]: IAuthModuleService
|
||||||
[Modules.CACHE]: ICacheService
|
[Modules.CACHE]: ICacheService
|
||||||
[Modules.CART]: ICartModuleService
|
[Modules.CART]: ICartModuleService
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from "./mutations"
|
||||||
|
export * from "./service"
|
||||||
|
export * from "./provider"
|
||||||
|
export * from "./providers"
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
export interface TrackAnalyticsEventDTO {
|
||||||
|
/**
|
||||||
|
* The event name
|
||||||
|
*/
|
||||||
|
event: string
|
||||||
|
/**
|
||||||
|
* The actor of the event, if there is any
|
||||||
|
*/
|
||||||
|
actor_id?: string
|
||||||
|
/**
|
||||||
|
* The group that the event is for, such as an organization or team.
|
||||||
|
* The "type" defines the name of the group (eg. "organization"), and the "id" is the id of the group.
|
||||||
|
*/
|
||||||
|
group?: {
|
||||||
|
type?: string
|
||||||
|
id?: string
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The properties of the event. The format and content depends on the provider.
|
||||||
|
*/
|
||||||
|
properties?: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IdentifyActorDTO {
|
||||||
|
actor_id: string
|
||||||
|
properties?: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IdentifyGroupDTO {
|
||||||
|
group: {
|
||||||
|
type: string
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
// When identifying a group, the actor can potentially be passed as well as metadata.
|
||||||
|
actor_id?: string
|
||||||
|
properties?: Record<string, any>
|
||||||
|
}
|
||||||
|
// Either actor_id or group must be provided. Depending on the provided identifier, the properties will be set for the actor or group.
|
||||||
|
export type IdentifyAnalyticsEventDTO = IdentifyActorDTO | IdentifyGroupDTO
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { IdentifyAnalyticsEventDTO, TrackAnalyticsEventDTO } from "./mutations"
|
||||||
|
|
||||||
|
export type ProviderTrackAnalyticsEventDTO = TrackAnalyticsEventDTO
|
||||||
|
|
||||||
|
export type ProviderIdentifyAnalyticsEventDTO = IdentifyAnalyticsEventDTO
|
||||||
|
|
||||||
|
export interface IAnalyticsProvider {
|
||||||
|
/**
|
||||||
|
* This method is used to track an event in the analytics provider
|
||||||
|
*
|
||||||
|
* @param {ProviderTrackAnalyticsEventDTO} data - The data for the event.
|
||||||
|
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
track(data: ProviderTrackAnalyticsEventDTO): Promise<void>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to identify an actor or group in the analytics provider
|
||||||
|
*
|
||||||
|
* @param {ProviderIdentifyAnalyticsEventDTO} data - The data for the actor or group..
|
||||||
|
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to shutdown the analytics provider, and flush all data before shutting down.
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>} Resolves when the provider is shutdown successfully.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
shutdown?(): Promise<void>
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./posthog"
|
||||||
|
export * from "./local"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export interface LocalAnalyticsServiceOptions {}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
export interface PosthogAnalyticsServiceOptions {
|
||||||
|
/**
|
||||||
|
* The key for the posthog events
|
||||||
|
*/
|
||||||
|
posthogEventsKey: string
|
||||||
|
/**
|
||||||
|
* The endpoint for the posthog server
|
||||||
|
*/
|
||||||
|
posthogHost: string
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { IModuleService } from "../modules-sdk"
|
||||||
|
import { IdentifyAnalyticsEventDTO, TrackAnalyticsEventDTO } from "./mutations"
|
||||||
|
import { IAnalyticsProvider } from "./provider"
|
||||||
|
|
||||||
|
export interface IAnalyticsModuleService extends IModuleService {
|
||||||
|
/**
|
||||||
|
* Returns a reference to the analytics provider in use
|
||||||
|
*/
|
||||||
|
getProvider(): IAnalyticsProvider
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method tracks an event in the analytics provider
|
||||||
|
*
|
||||||
|
* @param {TrackAnalyticsEventDTO} data - The data for the event.
|
||||||
|
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* await analyticsModuleService.track({
|
||||||
|
* event: "product_viewed",
|
||||||
|
* properties: {
|
||||||
|
* product_id: "123",
|
||||||
|
* product_name: "Product Name"
|
||||||
|
* }
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
track(data: TrackAnalyticsEventDTO): Promise<void>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method identifies an actor or group in the analytics provider
|
||||||
|
*
|
||||||
|
* @param {IdentifyAnalyticsEventDTO} data - The data for the actor or group.
|
||||||
|
* @returns {Promise<void>} Resolves when the actor or group is identified successfully.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* await analyticsModuleService.identify({
|
||||||
|
* actor_id: "123",
|
||||||
|
* properties: {
|
||||||
|
* name: "John Doe"
|
||||||
|
* }
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
identify(data: IdentifyAnalyticsEventDTO): Promise<void>
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * as AdminTypes from "./admin"
|
export * as AdminTypes from "./admin"
|
||||||
|
export * as AnalyticsTypes from "./analytics"
|
||||||
export * as ApiKeyTypes from "./api-key"
|
export * as ApiKeyTypes from "./api-key"
|
||||||
export * as AuthTypes from "./auth"
|
export * as AuthTypes from "./auth"
|
||||||
export * as CacheTypes from "./cache"
|
export * as CacheTypes from "./cache"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export * from "./address"
|
export * from "./address"
|
||||||
export * from "./admin"
|
export * from "./admin"
|
||||||
|
export * from "./analytics"
|
||||||
export * from "./api-key"
|
export * from "./api-key"
|
||||||
export * from "./auth"
|
export * from "./auth"
|
||||||
export * from "./bundles"
|
export * from "./bundles"
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
import {
|
||||||
|
IAnalyticsProvider,
|
||||||
|
ProviderIdentifyAnalyticsEventDTO,
|
||||||
|
ProviderTrackAnalyticsEventDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### constructor
|
||||||
|
*
|
||||||
|
* The constructor allows you to access resources from the module's container using the first parameter,
|
||||||
|
* and the module's options using the second parameter.
|
||||||
|
*
|
||||||
|
* If you're creating a client or establishing a connection with a third-party service, do it in the constructor.
|
||||||
|
*
|
||||||
|
* #### Example
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* import { Logger } from "@medusajs/framework/types"
|
||||||
|
* import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"
|
||||||
|
*
|
||||||
|
* type InjectedDependencies = {
|
||||||
|
* logger: Logger
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* type Options = {
|
||||||
|
* apiKey: string
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||||
|
* protected logger_: Logger
|
||||||
|
* protected options_: Options
|
||||||
|
* static identifier = "my-analytics"
|
||||||
|
* // assuming you're initializing a client
|
||||||
|
* protected client
|
||||||
|
*
|
||||||
|
* constructor (
|
||||||
|
* { logger }: InjectedDependencies,
|
||||||
|
* options: Options
|
||||||
|
* ) {
|
||||||
|
* super()
|
||||||
|
*
|
||||||
|
* this.logger_ = logger
|
||||||
|
* this.options_ = options
|
||||||
|
*
|
||||||
|
* // assuming you're initializing a client
|
||||||
|
* this.client = new Client(options)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* export default MyAnalyticsProviderService
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export class AbstractAnalyticsProviderService implements IAnalyticsProvider {
|
||||||
|
/**
|
||||||
|
* Each analytics provider has a unique ID used to identify it. The provider's ID
|
||||||
|
* will be stored as `aly_{identifier}_{id}`, where `{id}` is the provider's `id`
|
||||||
|
* property in the `medusa-config.ts`.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||||
|
* static identifier = "my-analytics"
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
static identifier: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
getIdentifier() {
|
||||||
|
return (this.constructor as any).identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method tracks an event using your provider's semantics
|
||||||
|
*
|
||||||
|
* This method will be used when tracking events to third-party providers.
|
||||||
|
*
|
||||||
|
* @param {ProviderTrackAnalyticsEventDTO} data - The data for the event.
|
||||||
|
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||||
|
* // ...
|
||||||
|
* async track(
|
||||||
|
* data: ProviderTrackAnalyticsEventDTO
|
||||||
|
* ): Promise<void> {
|
||||||
|
* // track event to third-party provider
|
||||||
|
* // or using custom logic
|
||||||
|
* // for example:
|
||||||
|
* this.client.track(data)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||||
|
throw Error("track must be overridden by the child class")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method identifies an actor or group in the analytics provider
|
||||||
|
*
|
||||||
|
* @param {ProviderIdentifyAnalyticsEventDTO} data - The data for the actor or group.
|
||||||
|
* @returns {Promise<void>} Resolves when the actor or group is identified successfully.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||||
|
* // ...
|
||||||
|
* async identify(
|
||||||
|
* data: ProviderIdentifyAnalyticsEventDTO
|
||||||
|
* ): Promise<void> {
|
||||||
|
* // identify actor or group in the analytics provider
|
||||||
|
* // or using custom logic
|
||||||
|
* // for example:
|
||||||
|
* this.client.identify(data)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||||
|
throw Error("identify must be overridden by the child class")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./abstract-analytics-provider"
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from "./api-key"
|
export * from "./api-key"
|
||||||
|
export * from "./analytics"
|
||||||
export * from "./auth"
|
export * from "./auth"
|
||||||
export * from "./bundles"
|
export * from "./bundles"
|
||||||
export * from "./common"
|
export * from "./common"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export const Modules = {
|
export const Modules = {
|
||||||
|
ANALYTICS: "analytics",
|
||||||
AUTH: "auth",
|
AUTH: "auth",
|
||||||
CACHE: "cache",
|
CACHE: "cache",
|
||||||
CART: "cart",
|
CART: "cart",
|
||||||
@@ -28,6 +29,7 @@ export const Modules = {
|
|||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const MODULE_PACKAGE_NAMES = {
|
export const MODULE_PACKAGE_NAMES = {
|
||||||
|
[Modules.ANALYTICS]: "@medusajs/medusa/analytics",
|
||||||
[Modules.AUTH]: "@medusajs/medusa/auth",
|
[Modules.AUTH]: "@medusajs/medusa/auth",
|
||||||
[Modules.CACHE]: "@medusajs/medusa/cache-inmemory",
|
[Modules.CACHE]: "@medusajs/medusa/cache-inmemory",
|
||||||
[Modules.CART]: "@medusajs/medusa/cart",
|
[Modules.CART]: "@medusajs/medusa/cart",
|
||||||
|
|||||||
@@ -66,6 +66,9 @@
|
|||||||
"@inquirer/checkbox": "^2.3.11",
|
"@inquirer/checkbox": "^2.3.11",
|
||||||
"@inquirer/input": "^2.2.9",
|
"@inquirer/input": "^2.2.9",
|
||||||
"@medusajs/admin-bundler": "2.8.2",
|
"@medusajs/admin-bundler": "2.8.2",
|
||||||
|
"@medusajs/analytics": "2.8.2",
|
||||||
|
"@medusajs/analytics-local": "2.8.2",
|
||||||
|
"@medusajs/analytics-posthog": "2.8.2",
|
||||||
"@medusajs/api-key": "2.8.2",
|
"@medusajs/api-key": "2.8.2",
|
||||||
"@medusajs/auth": "2.8.2",
|
"@medusajs/auth": "2.8.2",
|
||||||
"@medusajs/auth-emailpass": "2.8.2",
|
"@medusajs/auth-emailpass": "2.8.2",
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import AnalyticsLocalModule from "@medusajs/analytics-local"
|
||||||
|
|
||||||
|
export * from "@medusajs/analytics-local"
|
||||||
|
|
||||||
|
export default AnalyticsLocalModule
|
||||||
|
export const discoveryPath = require.resolve("@medusajs/analytics-local")
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import AnalyticsPosthogModule from "@medusajs/analytics-posthog"
|
||||||
|
|
||||||
|
export * from "@medusajs/analytics-posthog"
|
||||||
|
|
||||||
|
export default AnalyticsPosthogModule
|
||||||
|
export const discoveryPath = require.resolve("@medusajs/analytics-posthog")
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import AnalyticsModule from "@medusajs/analytics"
|
||||||
|
|
||||||
|
export * from "@medusajs/analytics"
|
||||||
|
|
||||||
|
export default AnalyticsModule
|
||||||
|
export const discoveryPath = require.resolve("@medusajs/analytics")
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/dist
|
||||||
|
node_modules
|
||||||
|
.DS_store
|
||||||
|
.env*
|
||||||
|
.env
|
||||||
|
*.sql
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# @medusajs/analytics
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# Analytics Module
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
ProviderIdentifyAnalyticsEventDTO,
|
||||||
|
ProviderTrackAnalyticsEventDTO,
|
||||||
|
} from "@medusajs/framework/types"
|
||||||
|
import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"
|
||||||
|
|
||||||
|
export class AnalyticsProviderServiceFixtures extends AbstractAnalyticsProviderService {
|
||||||
|
static identifier = "fixtures-analytics-provider"
|
||||||
|
|
||||||
|
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
async shutdown(): Promise<void> {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const services = [AnalyticsProviderServiceFixtures]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./default-provider"
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
|
import { Modules } from "@medusajs/framework/utils"
|
||||||
|
import { resolve } from "path"
|
||||||
|
import { IAnalyticsModuleService } from "@medusajs/types"
|
||||||
|
import { AnalyticsProviderServiceFixtures } from "../__fixtures__/providers/default-provider"
|
||||||
|
|
||||||
|
jest.setTimeout(100000)
|
||||||
|
|
||||||
|
const moduleOptions = {
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
resolve: resolve(
|
||||||
|
process.cwd() +
|
||||||
|
"/integration-tests/__fixtures__/providers/default-provider"
|
||||||
|
),
|
||||||
|
id: "default-provider",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
moduleIntegrationTestRunner<IAnalyticsModuleService>({
|
||||||
|
moduleName: Modules.ANALYTICS,
|
||||||
|
moduleOptions: moduleOptions,
|
||||||
|
testSuite: ({ service }) => {
|
||||||
|
describe("Analytics Module Service", () => {
|
||||||
|
let spies: {
|
||||||
|
track: jest.SpyInstance
|
||||||
|
identify: jest.SpyInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
spies = {
|
||||||
|
track: jest.spyOn(
|
||||||
|
AnalyticsProviderServiceFixtures.prototype,
|
||||||
|
"track"
|
||||||
|
),
|
||||||
|
identify: jest.spyOn(
|
||||||
|
AnalyticsProviderServiceFixtures.prototype,
|
||||||
|
"identify"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should call the provider's track method", async () => {
|
||||||
|
await service.track({
|
||||||
|
event: "test-event",
|
||||||
|
actor_id: "test-user",
|
||||||
|
properties: {
|
||||||
|
test: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(spies.track).toHaveBeenCalledWith({
|
||||||
|
event: "test-event",
|
||||||
|
actor_id: "test-user",
|
||||||
|
properties: {
|
||||||
|
test: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should call the provider's identify method to identify an actor", async () => {
|
||||||
|
await service.identify({
|
||||||
|
actor_id: "test-user",
|
||||||
|
properties: {
|
||||||
|
test: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(spies.identify).toHaveBeenCalledWith({
|
||||||
|
actor_id: "test-user",
|
||||||
|
properties: {
|
||||||
|
test: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should call the provider's identify method to identify a group", async () => {
|
||||||
|
await service.identify({
|
||||||
|
group: {
|
||||||
|
type: "organization",
|
||||||
|
id: "test-organization",
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
test: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(spies.identify).toHaveBeenCalledWith({
|
||||||
|
group: {
|
||||||
|
type: "organization",
|
||||||
|
id: "test-organization",
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
test: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
const defineJestConfig = require("../../../define_jest_config")
|
||||||
|
module.exports = defineJestConfig({
|
||||||
|
moduleNameMapper: {
|
||||||
|
"^@models": "<rootDir>/src/models",
|
||||||
|
"^@services": "<rootDir>/src/services",
|
||||||
|
"^@repositories": "<rootDir>/src/repositories",
|
||||||
|
"^@types": "<rootDir>/src/types",
|
||||||
|
"^@utils": "<rootDir>/src/utils",
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "@medusajs/analytics",
|
||||||
|
"version": "2.8.2",
|
||||||
|
"description": "Medusa Analytics module",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"!dist/**/__tests__",
|
||||||
|
"!dist/**/__mocks__",
|
||||||
|
"!dist/**/__fixtures__"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/medusajs/medusa",
|
||||||
|
"directory": "packages/modules/analytics"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"author": "Medusa",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"watch": "tsc --build --watch",
|
||||||
|
"watch:test": "tsc --build tsconfig.spec.json --watch",
|
||||||
|
"resolve:aliases": "tsc --showConfig -p tsconfig.json > tsconfig.resolved.json && tsc-alias -p tsconfig.resolved.json && rimraf tsconfig.resolved.json",
|
||||||
|
"build": "rimraf dist && tsc --build && npm run resolve:aliases",
|
||||||
|
"test": "jest --runInBand --passWithNoTests --bail --forceExit -- src",
|
||||||
|
"test:integration": "jest --forceExit -- integration-tests/**/__tests__/**/*.ts"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@medusajs/framework": "2.8.2",
|
||||||
|
"@medusajs/test-utils": "2.8.2",
|
||||||
|
"@swc/core": "^1.7.28",
|
||||||
|
"@swc/jest": "^0.2.36",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"tsc-alias": "^1.8.6",
|
||||||
|
"typescript": "^5.6.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@medusajs/framework": "2.8.2",
|
||||||
|
"awilix": "^8.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { Module, Modules } from "@medusajs/framework/utils"
|
||||||
|
import AnalyticsService from "./services/analytics-service"
|
||||||
|
import loadProviders from "./loaders/providers"
|
||||||
|
|
||||||
|
export default Module(Modules.ANALYTICS, {
|
||||||
|
service: AnalyticsService,
|
||||||
|
loaders: [loadProviders],
|
||||||
|
})
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { moduleProviderLoader } from "@medusajs/framework/modules-sdk"
|
||||||
|
import {
|
||||||
|
LoaderOptions,
|
||||||
|
ModuleProvider,
|
||||||
|
ModulesSdkTypes,
|
||||||
|
} from "@medusajs/framework/types"
|
||||||
|
import { asFunction, asValue, Lifetime } from "awilix"
|
||||||
|
import ProviderService, {
|
||||||
|
AnalyticsProviderIdentifierRegistrationName,
|
||||||
|
AnalyticsProviderRegistrationPrefix,
|
||||||
|
} from "../services/provider-service"
|
||||||
|
|
||||||
|
const registrationFn = async (klass, container, pluginOptions) => {
|
||||||
|
const key = ProviderService.getRegistrationIdentifier(klass, pluginOptions.id)
|
||||||
|
|
||||||
|
container.register({
|
||||||
|
[AnalyticsProviderRegistrationPrefix + key]: asFunction(
|
||||||
|
(cradle) => new klass(cradle, pluginOptions.options ?? {}),
|
||||||
|
{
|
||||||
|
lifetime: klass.LIFE_TIME || Lifetime.SINGLETON,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
container.registerAdd(
|
||||||
|
AnalyticsProviderIdentifierRegistrationName,
|
||||||
|
asValue(key)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async ({
|
||||||
|
container,
|
||||||
|
options,
|
||||||
|
}: LoaderOptions<
|
||||||
|
(
|
||||||
|
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||||
|
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||||
|
) & { providers: ModuleProvider[] }
|
||||||
|
>): Promise<void> => {
|
||||||
|
await moduleProviderLoader({
|
||||||
|
container,
|
||||||
|
providers: options?.providers || [],
|
||||||
|
registerServiceFn: registrationFn,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import {
|
||||||
|
TrackAnalyticsEventDTO,
|
||||||
|
IdentifyAnalyticsEventDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import AnalyticsProviderService from "./provider-service"
|
||||||
|
import { MedusaError } from "../../../../core/utils/dist/common"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
analyticsProviderService: AnalyticsProviderService
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class AnalyticsService {
|
||||||
|
protected readonly analyticsProviderService_: AnalyticsProviderService
|
||||||
|
|
||||||
|
constructor({ analyticsProviderService }: InjectedDependencies) {
|
||||||
|
this.analyticsProviderService_ = analyticsProviderService
|
||||||
|
}
|
||||||
|
|
||||||
|
__hooks = {
|
||||||
|
onApplicationShutdown: async () => {
|
||||||
|
await this.analyticsProviderService_.shutdown()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
getProvider() {
|
||||||
|
return this.analyticsProviderService_
|
||||||
|
}
|
||||||
|
|
||||||
|
async track(data: TrackAnalyticsEventDTO): Promise<void> {
|
||||||
|
try {
|
||||||
|
await this.analyticsProviderService_.track(data)
|
||||||
|
} catch (error) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.UNEXPECTED_STATE,
|
||||||
|
`Error tracking event for ${data.event}: ${error.message}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async identify(data: IdentifyAnalyticsEventDTO): Promise<void> {
|
||||||
|
try {
|
||||||
|
await this.analyticsProviderService_.identify(data)
|
||||||
|
} catch (error) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.UNEXPECTED_STATE,
|
||||||
|
`Error identifying event for ${
|
||||||
|
"group" in data ? data.group.id : data.actor_id
|
||||||
|
}: ${error.message}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { MedusaError } from "@medusajs/framework/utils"
|
||||||
|
import {
|
||||||
|
Constructor,
|
||||||
|
IAnalyticsProvider,
|
||||||
|
ProviderIdentifyAnalyticsEventDTO,
|
||||||
|
ProviderTrackAnalyticsEventDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
|
||||||
|
export const AnalyticsProviderIdentifierRegistrationName =
|
||||||
|
"analytics_providers_identifier"
|
||||||
|
|
||||||
|
export const AnalyticsProviderRegistrationPrefix = "aly_"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
[
|
||||||
|
key: `${typeof AnalyticsProviderRegistrationPrefix}${string}`
|
||||||
|
]: IAnalyticsProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class AnalyticsProviderService {
|
||||||
|
protected readonly analyticsProvider_: IAnalyticsProvider
|
||||||
|
|
||||||
|
constructor(container: InjectedDependencies) {
|
||||||
|
const analyticsProviderKeys = Object.keys(container).filter((k) =>
|
||||||
|
k.startsWith(AnalyticsProviderRegistrationPrefix)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (analyticsProviderKeys.length !== 1) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Analytics module should be initialized with exactly one provider`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.analyticsProvider_ = container[analyticsProviderKeys[0]]
|
||||||
|
}
|
||||||
|
|
||||||
|
static getRegistrationIdentifier(
|
||||||
|
providerClass: Constructor<IAnalyticsProvider>,
|
||||||
|
optionName?: string
|
||||||
|
) {
|
||||||
|
return `${(providerClass as any).identifier}_${optionName}`
|
||||||
|
}
|
||||||
|
|
||||||
|
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||||
|
this.analyticsProvider_.track(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||||
|
this.analyticsProvider_.identify(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async shutdown(): Promise<void> {
|
||||||
|
await this.analyticsProvider_.shutdown?.()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import {
|
||||||
|
ModuleProviderExports,
|
||||||
|
ModuleServiceInitializeOptions,
|
||||||
|
} from "@medusajs/framework/types"
|
||||||
|
|
||||||
|
export type AnalyticsModuleOptions = Partial<ModuleServiceInitializeOptions> & {
|
||||||
|
/**
|
||||||
|
* Providers to be registered
|
||||||
|
*/
|
||||||
|
provider?: {
|
||||||
|
/**
|
||||||
|
* The module provider to be registered
|
||||||
|
*/
|
||||||
|
resolve: string | ModuleProviderExports
|
||||||
|
/**
|
||||||
|
* The id of the provider
|
||||||
|
*/
|
||||||
|
id: string
|
||||||
|
/**
|
||||||
|
* key value pair of the configuration to be passed to the provider constructor
|
||||||
|
*/
|
||||||
|
options?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../../_tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@services": ["./src/services"],
|
||||||
|
"@types": ["./src/types"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Whitespace-only changes.
@@ -0,0 +1 @@
|
|||||||
|
# @medusajs/analytics-local
|
||||||
Whitespace-only changes.
@@ -0,0 +1,6 @@
|
|||||||
|
const defineJestConfig = require("../../../../define_jest_config")
|
||||||
|
module.exports = defineJestConfig({
|
||||||
|
moduleNameMapper: {
|
||||||
|
"^@services": "<rootDir>/src/services",
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "@medusajs/analytics-local",
|
||||||
|
"version": "2.8.2",
|
||||||
|
"description": "Local analytics provider for Medusa",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/medusajs/medusa",
|
||||||
|
"directory": "packages/modules/providers/analytics-local"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"!dist/**/__tests__",
|
||||||
|
"!dist/**/__mocks__",
|
||||||
|
"!dist/**/__fixtures__"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"author": "Medusa",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest --passWithNoTests src",
|
||||||
|
"build": "rimraf dist && tsc --build ./tsconfig.json",
|
||||||
|
"watch": "tsc --watch"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@medusajs/framework": "2.8.2",
|
||||||
|
"@swc/core": "^1.7.28",
|
||||||
|
"@swc/jest": "^0.2.36",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"rimraf": "^5.0.1",
|
||||||
|
"typescript": "^5.6.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@medusajs/framework": "2.8.2"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"medusa-plugin",
|
||||||
|
"medusa-plugin-analytics"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { ModuleProvider, Modules } from "@medusajs/framework/utils"
|
||||||
|
import { LocalAnalyticsService } from "./services/local-analytics"
|
||||||
|
|
||||||
|
const services = [LocalAnalyticsService]
|
||||||
|
|
||||||
|
export default ModuleProvider(Modules.ANALYTICS, {
|
||||||
|
services,
|
||||||
|
})
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {
|
||||||
|
LocalAnalyticsServiceOptions,
|
||||||
|
Logger,
|
||||||
|
ProviderIdentifyAnalyticsEventDTO,
|
||||||
|
ProviderTrackAnalyticsEventDTO,
|
||||||
|
} from "@medusajs/framework/types"
|
||||||
|
import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
logger: Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LocalAnalyticsService extends AbstractAnalyticsProviderService {
|
||||||
|
static identifier = "analytics-local"
|
||||||
|
protected config_: LocalAnalyticsServiceOptions
|
||||||
|
protected logger_: Logger
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
{ logger }: InjectedDependencies,
|
||||||
|
options: LocalAnalyticsServiceOptions
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
this.config_ = options
|
||||||
|
this.logger_ = logger
|
||||||
|
}
|
||||||
|
|
||||||
|
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||||
|
this.logger_.debug(
|
||||||
|
`Tracking event: '${data.event}', actor_id: '${
|
||||||
|
data.actor_id ?? "-"
|
||||||
|
}', group: '${data.group?.id ?? "-"}', properties: '${JSON.stringify(
|
||||||
|
data.properties
|
||||||
|
)}'`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||||
|
this.logger_.debug(
|
||||||
|
`Identifying user: '${data.actor_id ?? "-"}', group: '${
|
||||||
|
"group" in data ? data.group.id : "-"
|
||||||
|
}', properties: '${JSON.stringify(data.properties)}'`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../../../_tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@services": ["./src/services"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Whitespace-only changes.
@@ -0,0 +1 @@
|
|||||||
|
# @medusajs/analytics-posthog
|
||||||
Whitespace-only changes.
@@ -0,0 +1,6 @@
|
|||||||
|
const defineJestConfig = require("../../../../define_jest_config")
|
||||||
|
module.exports = defineJestConfig({
|
||||||
|
moduleNameMapper: {
|
||||||
|
"^@services": "<rootDir>/src/services",
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "@medusajs/analytics-posthog",
|
||||||
|
"version": "2.8.2",
|
||||||
|
"description": "Posthog analytics provider for Medusa",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/medusajs/medusa",
|
||||||
|
"directory": "packages/modules/providers/analytics-posthog"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"!dist/**/__tests__",
|
||||||
|
"!dist/**/__mocks__",
|
||||||
|
"!dist/**/__fixtures__"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"author": "Medusa",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest --passWithNoTests src",
|
||||||
|
"build": "rimraf dist && tsc --build ./tsconfig.json",
|
||||||
|
"watch": "tsc --watch"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@medusajs/framework": "2.8.2",
|
||||||
|
"@swc/core": "^1.7.28",
|
||||||
|
"@swc/jest": "^0.2.36",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"posthog-node": "^4.17.1",
|
||||||
|
"rimraf": "^5.0.1",
|
||||||
|
"typescript": "^5.6.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@medusajs/framework": "2.8.2"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"medusa-plugin",
|
||||||
|
"medusa-plugin-analytics"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { ModuleProvider, Modules } from "@medusajs/framework/utils"
|
||||||
|
import { PosthogAnalyticsService } from "./services/posthog-analytics"
|
||||||
|
|
||||||
|
const services = [PosthogAnalyticsService]
|
||||||
|
|
||||||
|
export default ModuleProvider(Modules.ANALYTICS, {
|
||||||
|
services,
|
||||||
|
})
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import {
|
||||||
|
PosthogAnalyticsServiceOptions,
|
||||||
|
Logger,
|
||||||
|
ProviderIdentifyAnalyticsEventDTO,
|
||||||
|
ProviderTrackAnalyticsEventDTO,
|
||||||
|
} from "@medusajs/framework/types"
|
||||||
|
import { PostHog } from "posthog-node"
|
||||||
|
import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
logger: Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PosthogAnalyticsService extends AbstractAnalyticsProviderService {
|
||||||
|
static identifier = "analytics-posthog"
|
||||||
|
protected config_: PosthogAnalyticsServiceOptions
|
||||||
|
protected logger_: Logger
|
||||||
|
protected client_: PostHog
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
{ logger }: InjectedDependencies,
|
||||||
|
options: PosthogAnalyticsServiceOptions
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
this.config_ = options
|
||||||
|
this.logger_ = logger
|
||||||
|
|
||||||
|
if (!options.posthogEventsKey) {
|
||||||
|
throw new Error("Posthog API key is not set, but is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client_ = new PostHog(options.posthogEventsKey, {
|
||||||
|
host: options.posthogHost || "https://eu.i.posthog.com",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||||
|
if (!data.event) {
|
||||||
|
throw new Error(
|
||||||
|
"Event name is required when tracking an event with Posthog"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.actor_id) {
|
||||||
|
throw new Error(
|
||||||
|
"Actor ID is required when tracking an event with Posthog"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.group?.id && !data.group?.type) {
|
||||||
|
throw new Error(
|
||||||
|
"Group type is required if passing group id when tracking an event with Posthog"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client_.capture({
|
||||||
|
event: data.event,
|
||||||
|
distinctId: data.actor_id,
|
||||||
|
properties: data.properties,
|
||||||
|
groups: data.group?.id
|
||||||
|
? { [data.group.type!]: data.group.id }
|
||||||
|
: undefined,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||||
|
if ("group" in data) {
|
||||||
|
this.client_.groupIdentify({
|
||||||
|
groupKey: data.group.id!,
|
||||||
|
groupType: data.group.type!,
|
||||||
|
properties: data.properties,
|
||||||
|
distinctId: data.actor_id,
|
||||||
|
})
|
||||||
|
} else if (data.actor_id) {
|
||||||
|
this.client_.identify({
|
||||||
|
distinctId: data.actor_id,
|
||||||
|
properties: data.properties,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
"Actor or group is required when identifying an entity with Posthog"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async shutdown() {
|
||||||
|
await this.client_.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../../../_tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@services": ["./src/services"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5820,6 +5820,55 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
"@medusajs/analytics-local@2.8.2, @medusajs/analytics-local@workspace:packages/modules/providers/analytics-local":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@medusajs/analytics-local@workspace:packages/modules/providers/analytics-local"
|
||||||
|
dependencies:
|
||||||
|
"@medusajs/framework": 2.8.2
|
||||||
|
"@swc/core": ^1.7.28
|
||||||
|
"@swc/jest": ^0.2.36
|
||||||
|
jest: ^29.7.0
|
||||||
|
rimraf: ^5.0.1
|
||||||
|
typescript: ^5.6.2
|
||||||
|
peerDependencies:
|
||||||
|
"@medusajs/framework": 2.8.2
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
|
"@medusajs/analytics-posthog@2.8.2, @medusajs/analytics-posthog@workspace:packages/modules/providers/analytics-posthog":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@medusajs/analytics-posthog@workspace:packages/modules/providers/analytics-posthog"
|
||||||
|
dependencies:
|
||||||
|
"@medusajs/framework": 2.8.2
|
||||||
|
"@swc/core": ^1.7.28
|
||||||
|
"@swc/jest": ^0.2.36
|
||||||
|
jest: ^29.7.0
|
||||||
|
posthog-node: ^4.17.1
|
||||||
|
rimraf: ^5.0.1
|
||||||
|
typescript: ^5.6.2
|
||||||
|
peerDependencies:
|
||||||
|
"@medusajs/framework": 2.8.2
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
|
"@medusajs/analytics@2.8.2, @medusajs/analytics@workspace:packages/modules/analytics":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@medusajs/analytics@workspace:packages/modules/analytics"
|
||||||
|
dependencies:
|
||||||
|
"@medusajs/framework": 2.8.2
|
||||||
|
"@medusajs/test-utils": 2.8.2
|
||||||
|
"@swc/core": ^1.7.28
|
||||||
|
"@swc/jest": ^0.2.36
|
||||||
|
jest: ^29.7.0
|
||||||
|
rimraf: ^3.0.2
|
||||||
|
tsc-alias: ^1.8.6
|
||||||
|
typescript: ^5.6.2
|
||||||
|
peerDependencies:
|
||||||
|
"@medusajs/framework": 2.8.2
|
||||||
|
awilix: ^8.0.1
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@medusajs/api-key@2.8.2, @medusajs/api-key@workspace:^, @medusajs/api-key@workspace:packages/modules/api-key":
|
"@medusajs/api-key@2.8.2, @medusajs/api-key@workspace:^, @medusajs/api-key@workspace:packages/modules/api-key":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@medusajs/api-key@workspace:packages/modules/api-key"
|
resolution: "@medusajs/api-key@workspace:packages/modules/api-key"
|
||||||
@@ -6583,6 +6632,9 @@ __metadata:
|
|||||||
"@inquirer/checkbox": ^2.3.11
|
"@inquirer/checkbox": ^2.3.11
|
||||||
"@inquirer/input": ^2.2.9
|
"@inquirer/input": ^2.2.9
|
||||||
"@medusajs/admin-bundler": 2.8.2
|
"@medusajs/admin-bundler": 2.8.2
|
||||||
|
"@medusajs/analytics": 2.8.2
|
||||||
|
"@medusajs/analytics-local": 2.8.2
|
||||||
|
"@medusajs/analytics-posthog": 2.8.2
|
||||||
"@medusajs/api-key": 2.8.2
|
"@medusajs/api-key": 2.8.2
|
||||||
"@medusajs/auth": 2.8.2
|
"@medusajs/auth": 2.8.2
|
||||||
"@medusajs/auth-emailpass": 2.8.2
|
"@medusajs/auth-emailpass": 2.8.2
|
||||||
@@ -16980,6 +17032,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"axios@npm:^1.8.2":
|
||||||
|
version: 1.9.0
|
||||||
|
resolution: "axios@npm:1.9.0"
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: ^1.15.6
|
||||||
|
form-data: ^4.0.0
|
||||||
|
proxy-from-env: ^1.1.0
|
||||||
|
checksum: 9371a56886c2e43e4ff5647b5c2c3c046ed0a3d13482ef1d0135b994a628c41fbad459796f101c655e62f0c161d03883454474d2e435b2e021b1924d9f24994c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"babel-jest@npm:^29.7.0":
|
"babel-jest@npm:^29.7.0":
|
||||||
version: 29.7.0
|
version: 29.7.0
|
||||||
resolution: "babel-jest@npm:29.7.0"
|
resolution: "babel-jest@npm:29.7.0"
|
||||||
@@ -29039,6 +29102,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"posthog-node@npm:^4.17.1":
|
||||||
|
version: 4.17.1
|
||||||
|
resolution: "posthog-node@npm:4.17.1"
|
||||||
|
dependencies:
|
||||||
|
axios: ^1.8.2
|
||||||
|
checksum: 31892ae0f03d28039f8081743b61f29dfb4479c0ff2e513a9e335d7872b869d2a30779c99e605a2482c99c7083b9b2bca81d2c3e3bf1d51fc3517de0335dfd52
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"preferred-pm@npm:^3.0.0":
|
"preferred-pm@npm:^3.0.0":
|
||||||
version: 3.1.3
|
version: 3.1.3
|
||||||
resolution: "preferred-pm@npm:3.1.3"
|
resolution: "preferred-pm@npm:3.1.3"
|
||||||
|
|||||||
Reference in new issue
Block a user