Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Workspaces support #1778

Merged
merged 49 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
517c8f2
Configure template to use workspaces
isaacroldan Mar 30, 2023
93c1cef
Only run install on root folder
isaacroldan Mar 30, 2023
119f08f
Only run install on root folder
isaacroldan Mar 30, 2023
5d833b4
Show warning if no workspaces in build/dev
isaacroldan Mar 30, 2023
b93df11
add a package.json file to the ui extensions templates
isaacroldan Mar 30, 2023
2ac804f
Only add extensions dependencies to root if not using workspaces
isaacroldan Mar 30, 2023
e0e5728
Fix issue with extension generate task list
isaacroldan Mar 31, 2023
bb9ee9e
Add command to migrate to worksapces
isaacroldan Apr 3, 2023
47595ab
Install extension dependencies after generating
isaacroldan Apr 6, 2023
dac1370
Remove migration command
isaacroldan Apr 6, 2023
0bfd2f6
Make dependency installtion more robust
isaacroldan Apr 6, 2023
3b0f2a4
Fix create-app tests
isaacroldan Apr 6, 2023
ea71638
Update oclif dependency in plugin-cloudflare
gonzaloriestra Apr 12, 2023
86226dd
Add private property (required for workspaces with yarn)
gonzaloriestra Apr 12, 2023
c75a11b
React as a peer dependency
gonzaloriestra Apr 21, 2023
3925eab
Merge branch 'main' into workspaces-support
gonzaloriestra Apr 24, 2023
3e0c14e
Update workspaces warning message
gonzaloriestra Apr 24, 2023
6a42ba8
Keep react as a dependency in cli-kit
gonzaloriestra Apr 24, 2023
0660791
Fix test
gonzaloriestra Apr 24, 2023
73f14ce
Fix tests
gonzaloriestra Apr 24, 2023
eaeeb67
Read dependencies from package.json
gonzaloriestra Apr 26, 2023
111147b
Fix react conflict with workspaces and npm
gonzaloriestra Apr 28, 2023
baae64c
React as a prod dependency for extensions
gonzaloriestra Apr 28, 2023
857e40e
Exit with error when running yarn from the repository
gonzaloriestra Apr 28, 2023
aa034d6
Merge branch 'main' into workspaces-support
gonzaloriestra Apr 28, 2023
9633810
Fix merge
gonzaloriestra Apr 28, 2023
6971e1c
Merge branch 'main' into workspaces-support
gonzaloriestra May 2, 2023
2cb6557
Fix merge
gonzaloriestra May 2, 2023
285c3ce
Merge branch 'main' into workspaces-support
isaacroldan May 8, 2023
f2a333c
Remove exact dependencies tests
isaacroldan May 8, 2023
ff3e3ca
Show workspaces warning in loader
isaacroldan May 8, 2023
4fa7806
Show workspaces warning in loader
isaacroldan May 8, 2023
2ff3687
Use switch to get the workspaces doc link
isaacroldan May 8, 2023
34d2a50
Update skip-dependencies flag to mark it as deprecated
isaacroldan May 8, 2023
5275ca6
update manifests
isaacroldan May 8, 2023
fa6502d
Dont manually edit the package.json from the CLI
isaacroldan May 8, 2023
8167ab6
Revert "Dont manually edit the package.json from the CLI"
isaacroldan May 8, 2023
1bc6589
Install just the required dependency for each extension
isaacroldan May 8, 2023
a2cdc6b
Merge branch 'main' into workspaces-support
isaacroldan May 8, 2023
f5fae74
use basic dependency instead of react one
isaacroldan May 8, 2023
9470562
Merge branch 'main' into workspaces-support
isaacroldan May 9, 2023
436ff04
Update packge.json.liquid for all extensions
isaacroldan May 10, 2023
7287ae1
Add react types as devDependency
isaacroldan May 10, 2023
63f7706
Merge branch 'main' into workspaces-support
isaacroldan May 12, 2023
9026c23
fix workspaces for pnpm and javascript functions
isaacroldan May 12, 2023
55a6ba7
Add JS function dependencies to the local package.json
isaacroldan May 12, 2023
9546a7e
Fix JS functions for non-worksapces
isaacroldan May 12, 2023
aa04179
Remove workspace warning
isaacroldan May 15, 2023
89e67d3
Undo cli-kit changes
gonzaloriestra May 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bin/shadowenv/yarn
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
printf "\033[1;32myarn \033[0;32mhas been superseded by \033[1;32mpnpm \033[0;32mso use that instead.\n\033[0m"
printf "\033[0;30mCheck out https://github.com/Shopify/cli/pull/870 to understand the rationale behind the move.\n"

exit 1
isaacroldan marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion packages/app/src/cli/models/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export async function getUIExtensionRendererVersion(
// Look for the vanilla JS version of the dependency (the react one depends on it, will always be present)
const rendererDependency = extension.dependency
if (!rendererDependency) return undefined
return getDependencyVersion(rendererDependency.name, app.directory)
return getDependencyVersion(rendererDependency, app.directory)
}

export async function getDependencyVersion(dependency: string, directory: string): Promise<RendererVersionResult> {
Expand Down
3 changes: 1 addition & 2 deletions packages/app/src/cli/models/app/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {BaseConfigContents} from '../extensions/schemas.js'
import {ExtensionFlavorValue} from '../../services/generate/extension.js'
import {TokenizedString} from '@shopify/cli-kit/node/output'
import {Result} from '@shopify/cli-kit/node/result'
import {DependencyVersion} from '@shopify/cli-kit/node/node-package-manager'

export type ExtensionCategory = 'ui' | 'function' | 'theme'

Expand Down Expand Up @@ -62,7 +61,7 @@ export type UIExtension<TConfiguration extends BaseConfigContents = BaseConfigCo
outputBundlePath: string
devUUID: string
surface: string
dependency?: DependencyVersion
dependency?: string
getBundleExtensionStdinContent(): string
validate(): Promise<Result<unknown, string>>
preDeployValidation(): Promise<void>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {createUIExtensionSpecification} from '../ui.js'
import {BaseUIExtensionSchema} from '../schemas.js'
import {outputContent, outputToken, TokenizedString} from '@shopify/cli-kit/node/output'

const dependency = {name: '@shopify/post-purchase-ui-extensions-react', version: '^0.13.2'}
const dependency = '@shopify/post-purchase-ui-extensions-react'

const spec = createUIExtensionSpecification({
identifier: 'checkout_post_purchase',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {BaseUIExtensionSchema} from '../schemas.js'
import {loadLocalesConfig} from '../../../utilities/extensions/locales-configuration.js'
import {zod} from '@shopify/cli-kit/node/schema'

const dependency = {name: '@shopify/checkout-ui-extensions-react', version: '^0.26.0'}
const dependency = '@shopify/checkout-ui-extensions-react'

const CheckoutSchema = BaseUIExtensionSchema.extend({
extensionPoints: zod.array(zod.string()).optional(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {loadLocalesConfig} from '../../../utilities/extensions/locales-configura
import {zod} from '@shopify/cli-kit/node/schema'
import {outputContent} from '@shopify/cli-kit/node/output'

const dependency = {name: '@shopify/customer-account-ui-extensions-react', version: '^0.0.20'}
const dependency = '@shopify/customer-account-ui-extensions-react'

const CustomerAccountsSchema = BaseUIExtensionSchema.extend({
categories: zod.array(zod.string()).optional(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {createUIExtensionSpecification} from '../ui.js'
import {BaseUIExtensionSchema} from '../schemas.js'
import {BugError} from '@shopify/cli-kit/node/error'

const dependency = {name: '@shopify/retail-ui-extensions-react', version: '1.0.0'}
const dependency = '@shopify/retail-ui-extensions-react'

const spec = createUIExtensionSpecification({
identifier: 'pos_ui_extension',
Expand All @@ -12,8 +12,8 @@ const spec = createUIExtensionSpecification({
partnersWebIdentifier: 'pos_ui_extension',
schema: BaseUIExtensionSchema,
deployConfig: async (config, directory) => {
const result = await getDependencyVersion(dependency.name, directory)
if (result === 'not_found') throw new BugError(`Dependency ${dependency.name} not found`)
const result = await getDependencyVersion(dependency, directory)
if (result === 'not_found') throw new BugError(`Dependency ${dependency} not found`)
return {
name: config.name,
description: config.description,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {createUIExtensionSpecification} from '../ui.js'
import {BaseUIExtensionSchema} from '../schemas.js'
import {BugError} from '@shopify/cli-kit/node/error'

const dependency = {name: '@shopify/admin-ui-extensions-react', version: '^1.0.1'}
const dependency = '@shopify/admin-ui-extensions-react'

const spec = createUIExtensionSpecification({
identifier: 'product_subscription',
Expand All @@ -13,8 +13,8 @@ const spec = createUIExtensionSpecification({
partnersWebIdentifier: 'product_subscription',
schema: BaseUIExtensionSchema,
deployConfig: async (_, directory) => {
const result = await getDependencyVersion(dependency.name, directory)
if (result === 'not_found') throw new BugError('Dependency @shopify/admin-ui-extensions-react not found')
const result = await getDependencyVersion(dependency, directory)
if (result === 'not_found') throw new BugError(`Dependency ${dependency} not found`)
return {renderer_version: result?.version}
},
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {fileExists} from '@shopify/cli-kit/node/fs'
import {joinPath} from '@shopify/cli-kit/node/path'
import {outputContent, outputToken} from '@shopify/cli-kit/node/output'

const dependency = {name: '@shopify/checkout-ui-extensions-react', version: '^0.26.0'}
const dependency = '@shopify/checkout-ui-extensions-react'

const UIExtensionSchema = BaseUIExtensionSchema.extend({
settings: zod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const kilobytes = 1024
const BUNDLE_SIZE_LIMIT_KB = 64
const BUNDLE_SIZE_LIMIT = BUNDLE_SIZE_LIMIT_KB * kilobytes

const dependency = {name: '@shopify/web-pixels-extension', version: '^0.1.1'}
const dependency = '@shopify/web-pixels-extension'

const WebPixelSchema = BaseUIExtensionSchema.extend({
runtimeContext: zod.string(),
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/cli/models/extensions/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface UIExtensionSpec<TConfiguration extends BaseConfigContents = Bas
supportedFlavors: ExtensionFlavor[]
gated: boolean
helpURL?: string
dependency?: {name: string; version: string}
dependency?: string
templatePath?: string
graphQLType?: string
schema: ZodSchemaType<TConfiguration>
Expand Down
7 changes: 6 additions & 1 deletion packages/app/src/cli/services/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {buildThemeExtensions, buildFunctionExtension, buildUIExtensions} from '.
import buildWeb from './web.js'
import {installAppDependencies} from './dependencies.js'
import {AppInterface, Web} from '../models/app/app.js'
import {showWorkspaceWarning} from '../utilities/app/workspaces-warning.js'
import {renderConcurrent, renderSuccess} from '@shopify/cli-kit/node/ui'
import {AbortSignal} from '@shopify/cli-kit/node/abort'
import {Writable} from 'stream'
Expand All @@ -13,10 +14,14 @@ interface BuildOptions {
}

async function build(options: BuildOptions) {
if (!options.skipDependenciesInstallation) {
if (!options.skipDependenciesInstallation && !options.app.usesWorkspaces) {
await installAppDependencies(options.app)
}

if (!options.app.usesWorkspaces) {
showWorkspaceWarning(options.app.packageManager)
}

const env: {SHOPIFY_API_KEY?: string} = {}
if (options.apiKey) {
env.SHOPIFY_API_KEY = options.apiKey
Expand Down
7 changes: 6 additions & 1 deletion packages/app/src/cli/services/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {getAppIdentifiers} from '../models/app/identifiers.js'
import {getAnalyticsTunnelType} from '../utilities/analytics.js'
import {buildAppURLForWeb} from '../utilities/app/app-url.js'
import {HostThemeManager} from '../utilities/host-theme-manager.js'
import {showWorkspaceWarning} from '../utilities/app/workspaces-warning.js'
import {Config} from '@oclif/core'
import {reportAnalyticsEvent} from '@shopify/cli-kit/node/analytics'
import {execCLI2} from '@shopify/cli-kit/node/ruby'
Expand Down Expand Up @@ -80,10 +81,14 @@ async function dev(options: DevOptions) {
const specifications = await fetchSpecifications({token, apiKey, config: options.commandConfig})
let localApp = await load({directory: options.directory, specifications})

if (!options.skipDependenciesInstallation) {
if (!options.skipDependenciesInstallation && !localApp.usesWorkspaces) {
localApp = await installAppDependencies(localApp)
}

if (!localApp.usesWorkspaces) {
showWorkspaceWarning(localApp.packageManager)
}
isaacroldan marked this conversation as resolved.
Show resolved Hide resolved

const frontendConfig = localApp.webs.find(({configuration}) => configuration.type === WebType.Frontend)
const backendConfig = localApp.webs.find(({configuration}) => configuration.type === WebType.Backend)
const webhooksPath = backendConfig?.configuration?.webhooksPath || '/api/webhooks'
Expand Down
84 changes: 32 additions & 52 deletions packages/app/src/cli/services/generate/extension.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
addExtensionDependencies,
generateExtension,
getExtensionRuntimeDependencies,
getFunctionRuntimeDependencies,
TemplateLanguage,
} from './extension.js'
Expand All @@ -25,7 +25,15 @@ import * as git from '@shopify/cli-kit/node/git'
import {joinPath, dirname} from '@shopify/cli-kit/node/path'
import type {ExtensionFlavorValue} from './extension.js'

vi.mock('@shopify/cli-kit/node/node-package-manager')
// vi.mock('@shopify/cli-kit/node/node-package-manager')
vi.mock('@shopify/cli-kit/node/node-package-manager', async () => {
const actual: any = await vi.importActual('@shopify/cli-kit/node/node-package-manager')
return {
...actual,
addNPMDependenciesIfNeeded: vi.fn(),
addResolutionOrOverride: vi.fn(),
}
})

describe('initialize a extension', async () => {
const allUISpecs = await loadLocalUIExtensionsSpecifications()
Expand Down Expand Up @@ -75,28 +83,14 @@ describe('initialize a extension', async () => {
appDirectory: tmpDir,
specifications,
})
const addDependenciesCalls = vi.mocked(addNPMDependenciesIfNeeded).mock.calls
expect(addDependenciesCalls.length).toEqual(2)

expect(vi.mocked(addNPMDependenciesIfNeeded)).toHaveBeenCalledTimes(2)

const loadedApp = await loadApp({directory: tmpDir, specifications})
const generatedExtension2 = loadedApp.extensions.ui.sort((lhs, rhs) =>
lhs.directory < rhs.directory ? -1 : 1,
)[1]!
expect(generatedExtension2.configuration.name).toBe(name2)

const firstDependenciesCallArgs = addDependenciesCalls[0]!
expect(firstDependenciesCallArgs[0]).toEqual([
{name: '@shopify/post-purchase-ui-extensions-react', version: '^0.13.2'},
])
expect(firstDependenciesCallArgs[1].type).toEqual('prod')
expect(firstDependenciesCallArgs[1].directory).toEqual(loadedApp.directory)

const secondDependencyCallArgs = addDependenciesCalls[1]!
expect(firstDependenciesCallArgs[0]).toEqual([
{name: '@shopify/post-purchase-ui-extensions-react', version: '^0.13.2'},
])
expect(secondDependencyCallArgs[1].type).toEqual('prod')
expect(secondDependencyCallArgs[1].directory).toEqual(loadedApp.directory)
})
})

Expand Down Expand Up @@ -397,42 +391,28 @@ describe('initialize a extension', async () => {
})
})

describe('getExtensionRuntimeDependencies', () => {
test('no not include React for flavored Vanilla UI extensions', async () => {
// Given
const allUISpecs = await loadLocalUIExtensionsSpecifications()
const extensionFlavor: ExtensionFlavorValue = 'vanilla-js'

// When/then
allUISpecs.forEach((specification) => {
const got = getExtensionRuntimeDependencies({specification, extensionFlavor})
expect(got.find((dep) => dep.name === 'react' && dep.version === '^17.0.0')).toBeFalsy()
})
})

test('includes React for flavored React UI extensions', async () => {
// Given
const allUISpecs = await loadLocalUIExtensionsSpecifications()
const extensionFlavor: ExtensionFlavorValue = 'react'
describe('addExtensionDependencies', () => {
test('copies the prod dependencies from the package.json', async () => {
await file.inTemporaryDirectory(async (tmpDir) => {
// Given
const packageJsonPath = joinPath(tmpDir, 'package.json')
await file.writeFile(
packageJsonPath,
JSON.stringify({
dependencies: {semver: '7.3.8'},
}),
)

// When/then
allUISpecs.forEach((specification) => {
const got = getExtensionRuntimeDependencies({specification, extensionFlavor})
expect(got.find((dep) => dep.name === 'react' && dep.version === '^17.0.0')).toBeTruthy()
})
})
// When
await addExtensionDependencies(packageJsonPath, '/app', 'npm')

test('includes the renderer package for UI extensions', async () => {
// Given
const allUISpecs = await loadLocalUIExtensionsSpecifications()

// When/then
allUISpecs.forEach((specification) => {
const reference = specification.dependency
if (reference) {
const got = getExtensionRuntimeDependencies({specification})
expect(got.find((dep) => dep.name === reference.name && dep.version === reference.version)).toBeTruthy()
}
// Then
expect(vi.mocked(addNPMDependenciesIfNeeded)).toHaveBeenCalledOnce()
expect(vi.mocked(addNPMDependenciesIfNeeded)).toHaveBeenNthCalledWith(1, [{name: 'semver', version: '7.3.8'}], {
packageManager: 'npm',
type: 'prod',
directory: '/app',
})
})
})
})
Expand Down
Loading