-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 18d9332
Showing
19 changed files
with
12,637 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Editor configuration, see http://editorconfig.org | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
indent_style = space | ||
indent_size = 4 | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
|
||
[*.json] | ||
indent_size = 2 | ||
|
||
[*.yml] | ||
indent_size = 2 | ||
|
||
[*.md] | ||
max_line_length = off | ||
trim_trailing_whitespace = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
github: prasmalla |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
*.launch | ||
*.log | ||
*.sqlite | ||
*.sublime-workspace | ||
.DS_Store | ||
.c9/ | ||
.cache | ||
.classpath | ||
.env | ||
.env.* | ||
.history | ||
.idea | ||
.project | ||
.sass-cache | ||
.settings/ | ||
.temp | ||
.vscode | ||
Thumbs.db | ||
__data__ | ||
bazel-out | ||
chrome-profiler-events*.json | ||
connect.lock | ||
coverage | ||
dist | ||
generated/ | ||
lib/ | ||
libpeerconnection.log | ||
node_modules | ||
out-tsc | ||
speed-measure-plugin*.json | ||
tmp | ||
typings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
generated-types.ts | ||
lazy-extensions.module.ts | ||
shared-extensions.module.ts | ||
generated-graphql-shop-errors.ts | ||
generated-graphql-admin-errors.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"singleQuote": true, | ||
"trailingComma": "all", | ||
"printWidth": 110, | ||
"arrowParens": "avoid" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
## Printful Vendure Plugin | ||
|
||
![Vendure version](https://img.shields.io/npm/dependency-version/@callit-today/vendure-plugin-printful/dev/@vendure/core) | ||
|
||
Import Printful products and start selling! | ||
|
||
|
||
# Getting started | ||
|
||
`yarn add @callit-today/vendure-plugin-printful` | ||
|
||
\ | ||
| ||
Add your `PRINTFUL_AUTH_TOKEN` to `.env` and run import GraphQL query in admin-api | ||
|
||
```graphql | ||
{ | ||
importPrintfulProducts | ||
} | ||
``` | ||
\ | ||
| ||
|
||
## How it works | ||
|
||
The plugin uses `FastImporterSerivce` to import products from Printful. Remember to rebuild search index after import completes. When an order is completed, a draft order is created in Printful. | ||
|
||
| ||
|
||
## Next steps | ||
|
||
Confirm the order in Printful for fulfillment. | ||
|
||
| ||
|
||
## Todo | ||
|
||
Add config option for auto confirming orders on Printful. | ||
|
||
\ | ||
| ||
|
||
## License | ||
|
||
MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"name": "@callit-today/vendure-plugin-printful", | ||
"version": "0.0.2", | ||
"description": "Vendure Plugin for Printful", | ||
"author": "CALLiT.today <[email protected]>", | ||
"repository": "https://github.com/calliT-today/vendure-plugin-printful", | ||
"license": "MIT", | ||
"private": false, | ||
"engines": { | ||
"node": ">=16.0.0" | ||
}, | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"files": [ | ||
"dist", | ||
"README.md" | ||
], | ||
"scripts": { | ||
"start": "yarn ts-node test/dev-server.ts", | ||
"build": "rimraf dist && tsc", | ||
"test": "jest --preset=\"ts-jest\"" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "29.4.0", | ||
"@vendure/admin-ui-plugin": "1.9.6", | ||
"@vendure/asset-server-plugin": "1.9.6", | ||
"@vendure/core": "1.9.6", | ||
"@vendure/testing": "1.9.6", | ||
"@vendure/ui-devkit": "1.9.6", | ||
"jest": "29.4.3", | ||
"printful-client": "^0.0.3", | ||
"rimraf": "^4.1.2", | ||
"ts-jest": "29.0.5", | ||
"ts-node": "10.9.1", | ||
"typescript": "4.9.5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { gql } from 'graphql-tag'; | ||
|
||
export const adminSchema = gql` | ||
extend type Query { | ||
importPrintfulProducts: String | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Resolver, Query } from '@nestjs/graphql'; | ||
import { Permission, Allow, RequestContext, Ctx } from '@vendure/core'; | ||
import { PrintfulService } from '../service/printful.service'; | ||
|
||
@Resolver() | ||
export class PrintfulResolver { | ||
constructor(private printfulService: PrintfulService) {} | ||
|
||
@Query() | ||
@Allow(Permission.Public) | ||
async importPrintfulProducts(@Ctx() ctx: RequestContext): Promise<void> { | ||
this.printfulService.importPrintfulProducts(ctx); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const loggerCtx = 'PrintfulPlugin'; | ||
export const PLUGIN_INIT_OPTIONS = Symbol('PRINTFUL_PLUGIN_INIT_OPTIONS'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './printful.plugin'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { Order, PluginCommonModule, TransactionalConnection, VendurePlugin } from '@vendure/core'; | ||
import { adminSchema } from './api/api-extensions'; | ||
import { PrintfulResolver } from './api/printful.resolver'; | ||
import { PLUGIN_INIT_OPTIONS } from './constants'; | ||
import { PrintfulClient } from 'printful-client'; | ||
import { PrintfulService } from './service/printful.service'; | ||
import { EntitySubscriberInterface, EventSubscriber, UpdateEvent } from 'typeorm'; | ||
import { Injectable } from '@nestjs/common'; | ||
|
||
export interface PrintfulOptions { | ||
enabled: boolean; | ||
} | ||
|
||
@Injectable() | ||
@EventSubscriber() | ||
export class OrderSubscriber implements EntitySubscriberInterface<Order> { | ||
constructor(private connection: TransactionalConnection) { | ||
this.connection.rawConnection.subscribers.push(this); | ||
} | ||
|
||
listenTo() { | ||
return Order; | ||
} | ||
|
||
async afterUpdate(event: UpdateEvent<Order>) { | ||
if (event.entity?.state !== 'PaymentAuthorized') return; | ||
try { | ||
const printfulClient = new PrintfulClient(process.env.PRINTFUL_AUTH_TOKEN as string); | ||
const orderItems = []; | ||
for (const line of event.entity?.lines) { | ||
const printfulOrderItem = { | ||
sync_variant_id: line.productVariant.sku, | ||
quantity: line.quantity, | ||
retail_price: `${line.unitPrice / 100}`, | ||
}; | ||
orderItems.push(printfulOrderItem); | ||
} | ||
const printfulOrder = { | ||
recipient: { | ||
name: event.entity?.shippingAddress?.fullName, | ||
address1: event.entity?.shippingAddress?.streetLine1, | ||
city: event.entity?.shippingAddress?.city, | ||
state_code: event.entity?.shippingAddress?.province.match(/\b\w/g).join(''), | ||
country_code: event.entity?.shippingAddress?.countryCode, | ||
zip: event.entity?.shippingAddress?.postalCode, | ||
}, | ||
items: orderItems, | ||
}; | ||
await printfulClient.orders.create(printfulOrder); | ||
} catch (e) { | ||
console.log(e); | ||
} | ||
} | ||
} | ||
|
||
@VendurePlugin({ | ||
imports: [PluginCommonModule], | ||
providers: [ | ||
{ | ||
provide: PLUGIN_INIT_OPTIONS, | ||
useFactory: () => PrintfulPlugin.options, | ||
}, | ||
PrintfulService, | ||
OrderSubscriber, | ||
], | ||
adminApiExtensions: { | ||
resolvers: [PrintfulResolver], | ||
schema: adminSchema, | ||
}, | ||
}) | ||
export class PrintfulPlugin { | ||
static options: PrintfulOptions; | ||
|
||
static init(options: PrintfulOptions) { | ||
this.options = options; | ||
return PrintfulPlugin; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { | ||
Asset, | ||
AssetService, | ||
ConfigService, | ||
FastImporterService, | ||
LanguageCode, | ||
ProductService, | ||
RequestContext, | ||
} from '@vendure/core'; | ||
import { | ||
CreateProductInput, | ||
CreateProductVariantInput, | ||
GlobalFlag, | ||
ProductTranslationInput, | ||
ProductVariantTranslationInput, | ||
} from '../../generated/generated-types'; | ||
import { PrintfulClient } from 'printful-client'; | ||
import { normalizeString } from '@vendure/common/lib/normalize-string'; | ||
|
||
@Injectable() | ||
export class PrintfulService { | ||
private printfulClient: PrintfulClient; | ||
|
||
constructor( | ||
private fastImporterService: FastImporterService, | ||
private configService: ConfigService, | ||
private assetService: AssetService, | ||
private productService: ProductService, | ||
) { | ||
this.printfulClient = new PrintfulClient(process.env.PRINTFUL_AUTH_TOKEN as string); | ||
} | ||
|
||
async getProductList(): Promise<any> { | ||
try { | ||
const response = await this.printfulClient.products.getAll(); | ||
return await response.json(); | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
} | ||
|
||
async getProductById(id: string): Promise<any> { | ||
try { | ||
const response = await this.printfulClient.products.get(id); | ||
return await response.json(); | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
} | ||
|
||
async importPrintfulProducts(ctx: RequestContext) { | ||
await this.fastImporterService.initialize(ctx.channel); | ||
const { assetImportStrategy } = this.configService.importExportOptions; | ||
|
||
const { result } = await this.getProductList(); | ||
for (const product of result) { | ||
const existingProduct = await this.productService.findOneBySlug( | ||
ctx, | ||
normalizeString(product.name as string, '-'), | ||
); | ||
if (!existingProduct) { | ||
const stream = await assetImportStrategy.getStreamFromPath(product.thumbnail_url); | ||
const asset = (await this.assetService.createFromFileStream(stream, 'assets', ctx)) as Asset; | ||
|
||
const productTranslation: ProductTranslationInput = { | ||
languageCode: LanguageCode.en, | ||
name: product.name, | ||
slug: product.name, | ||
description: 'Imported from Printful', | ||
}; | ||
const createProductInput: CreateProductInput = { | ||
featuredAssetId: asset.id as string, | ||
customFields: { printfulProductId: product.id }, | ||
translations: [productTranslation], | ||
}; | ||
const productId = await this.fastImporterService.createProduct(createProductInput); | ||
|
||
const { result } = await this.getProductById(product.id); | ||
for (const productVariant of result.sync_variants) { | ||
const stream = await assetImportStrategy.getStreamFromPath( | ||
productVariant.files[1].preview_url, | ||
); | ||
const asset = (await this.assetService.createFromFileStream( | ||
stream, | ||
'assets', | ||
ctx, | ||
)) as Asset; | ||
|
||
const productVariantTranslation: ProductVariantTranslationInput = { | ||
languageCode: LanguageCode.en, | ||
name: productVariant.name, | ||
}; | ||
const createProductVariantInput: CreateProductVariantInput = { | ||
featuredAssetId: asset.id as string, | ||
productId: productId as string, | ||
translations: [productVariantTranslation], | ||
sku: productVariant.id, | ||
price: productVariant.retail_price * 100, | ||
trackInventory: 'FALSE' as GlobalFlag, | ||
taxCategoryId: '1', | ||
}; | ||
await this.fastImporterService.createProductVariant(createProductVariantInput); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.