@playcademy/vite-plugin 0.0.1-beta.1 → 0.0.1-beta.10

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,20 @@
1
+ /**
2
+ * Manifest generation and build output functionality
3
+ */
4
+ import type { ResolvedConfig } from 'vite';
5
+ import type { ManifestV1 } from '@playcademy/types';
6
+ export interface PlaycademyOutputData {
7
+ manifestPath?: string;
8
+ manifestSizeKb?: string;
9
+ zipPath?: string;
10
+ zipSizeKb?: string;
11
+ }
12
+ export interface ManifestOptions {
13
+ bootMode: ManifestV1['bootMode'];
14
+ entryPoint: string;
15
+ styles: string[];
16
+ platform: ManifestV1['platform'];
17
+ }
18
+ export declare function generatePlaycademyManifest(config: ResolvedConfig, options: ManifestOptions, outDir: string, buildOutputs: PlaycademyOutputData): Promise<void>;
19
+ export declare function createOutputZipArchive(config: ResolvedConfig, outDir: string, buildOutputs: PlaycademyOutputData): Promise<void>;
20
+ export declare function performPlaycademyLogging(config: ResolvedConfig, buildOutputs: PlaycademyOutputData): void;
@@ -0,0 +1,9 @@
1
+ import { type ProjectInfo } from '../utils';
2
+ import type { ResolvedConfig } from 'vite';
3
+ interface SandboxManager {
4
+ url: string;
5
+ project: ProjectInfo | null;
6
+ cleanup: () => void;
7
+ }
8
+ export declare function startSandbox(viteConfig: ResolvedConfig, autoStart?: boolean, verbose?: boolean, customUrl?: string): Promise<SandboxManager>;
9
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { ViteDevServer } from 'vite';
2
+ import type { ProjectInfo } from '../utils';
3
+ export declare function devServerMiddleware(server: ViteDevServer, sandboxUrl: string, project: ProjectInfo): void;
Binary file
Binary file
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Utility functions for the Playcademy Vite plugin
3
+ */
4
+ import type { ResolvedConfig } from 'vite';
5
+ export interface ProjectInfo {
6
+ slug: string;
7
+ displayName: string;
8
+ version: string;
9
+ description?: string;
10
+ }
11
+ export declare function extractProjectInfo(viteConfig: ResolvedConfig): ProjectInfo;
12
+ export declare function formatNumberWithCommas(numStr: string): string;
13
+ export declare function findAvailablePort(startPort?: number): Promise<number>;
package/package.json CHANGED
@@ -1,27 +1,35 @@
1
1
  {
2
2
  "name": "@playcademy/vite-plugin",
3
+ "version": "0.0.1-beta.10",
3
4
  "type": "module",
4
- "version": "0.0.1-beta.1",
5
- "module": "src/index.ts",
6
5
  "exports": {
7
6
  ".": {
8
7
  "import": "./dist/index.js",
9
8
  "types": "./dist/index.d.ts"
10
9
  }
11
10
  },
11
+ "main": "dist/index.js",
12
+ "module": "dist/index.js",
13
+ "files": [
14
+ "dist"
15
+ ],
12
16
  "scripts": {
13
- "build": "bun build.ts",
14
- "pub": "bun run build && bunx bumpp --no-tag --no-push && bun publish --access public"
17
+ "build": "rm -rf dist && bun build.ts",
18
+ "bump": "bunx bumpp --no-tag --no-push -c \"chore(@playcademy/vite-plugin): release v%s\"",
19
+ "pub": "bun run build && bun run bump && bun publish --access public"
20
+ },
21
+ "dependencies": {
22
+ "archiver": "^7.0.1",
23
+ "picocolors": "^1.1.1"
15
24
  },
16
25
  "devDependencies": {
26
+ "@playcademy/sandbox": "0.1.0-beta.7",
27
+ "@playcademy/types": "latest",
17
28
  "@types/archiver": "^6.0.3",
18
- "@types/bun": "latest"
29
+ "@types/bun": "latest",
30
+ "yocto-spinner": "^0.2.2"
19
31
  },
20
32
  "peerDependencies": {
21
33
  "typescript": "^5"
22
- },
23
- "dependencies": {
24
- "archiver": "^7.0.1",
25
- "picocolors": "^1.1.1"
26
34
  }
27
35
  }
package/build.ts DELETED
@@ -1,45 +0,0 @@
1
- import { $ } from 'bun'
2
- import packageJson from './package.json' assert { type: 'json' }
3
- import yoctoSpinner from 'yocto-spinner'
4
-
5
- const startTime = performance.now()
6
- const spinner = yoctoSpinner({ text: 'Building JavaScript...' }).start()
7
-
8
- const buildDir = './dist'
9
- const entrypoints = ['./src/index.ts']
10
-
11
- try {
12
- await $`rm -rf ${buildDir}`
13
-
14
- await Bun.build({
15
- entrypoints,
16
- external: [...Object.keys(packageJson.peerDependencies)],
17
- outdir: buildDir,
18
- format: 'esm',
19
- target: 'node',
20
- })
21
-
22
- spinner.text = 'Generating types...'
23
-
24
- const { stderr } =
25
- await $`tsc --emitDeclarationOnly --declaration --project tsconfig.types.json --outDir ${buildDir}`
26
-
27
- if (stderr.toString().length) {
28
- spinner.error(`Type generation failed:\n${stderr.toString()}`)
29
- process.exit(1) // Exit with error code
30
- } else {
31
- const duration = ((performance.now() - startTime) / 1000).toFixed(2)
32
- spinner.success(`Build complete in ${duration}s!`)
33
-
34
- // Log built entrypoints
35
- for (const entry of entrypoints) {
36
- console.log(` - ${entry}`)
37
- }
38
- }
39
- process.exit(0)
40
- } catch (error) {
41
- const duration = ((performance.now() - startTime) / 1000).toFixed(2)
42
- console.log({ error })
43
- spinner.error(`Build failed in ${duration}s: ${error}`)
44
- process.exit(1) // Exit with error code
45
- }
package/src/index.ts DELETED
@@ -1,231 +0,0 @@
1
- import path from 'node:path'
2
- import fs from 'node:fs/promises'
3
- import { createWriteStream } from 'node:fs'
4
- import type { Plugin, ResolvedConfig } from 'vite'
5
- import { ManifestV1Schema, type ManifestV1 } from '@playcademy/data/schemas'
6
- import archiver from 'archiver'
7
- import pc from 'picocolors'
8
-
9
- export interface PlaycademyPluginOptions {
10
- bootMode?: ManifestV1['bootMode']
11
- entryPoint?: string
12
- styles?: string[]
13
- engine?: ManifestV1['engine']
14
- autoZip?: boolean
15
- }
16
-
17
- const LOG_LINE_TOTAL_WIDTH = 60
18
-
19
- interface PlaycademyOutputData {
20
- manifestPath?: string
21
- manifestSizeKb?: string
22
- zipPath?: string
23
- zipSizeKb?: string
24
- }
25
-
26
- function formatNumberWithCommas(numStr: string): string {
27
- if (!numStr) return numStr
28
- const parts = numStr.split('.')
29
- if (parts[0] === undefined) return numStr
30
- parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
31
- return parts.join('.')
32
- }
33
-
34
- async function generatePlaycademyManifest(
35
- config: ResolvedConfig,
36
- options: Required<Omit<PlaycademyPluginOptions, 'autoZip'>>,
37
- outDir: string,
38
- buildOutputs: PlaycademyOutputData,
39
- ) {
40
- const manifestData: ManifestV1 = {
41
- version: '1',
42
- bootMode: options.bootMode,
43
- entryPoint: options.entryPoint,
44
- styles: options.styles || [],
45
- engine: options.engine || 'custom',
46
- createdAt: new Date().toISOString(),
47
- }
48
-
49
- const validation = ManifestV1Schema.safeParse(manifestData)
50
-
51
- if (!validation.success) {
52
- console.error(
53
- '[Playcademy] Error validating generated manifest data:',
54
- validation.error.flatten(),
55
- )
56
- config.logger.error(
57
- '[Playcademy] Failed to generate valid manifest file.',
58
- )
59
- throw new Error('[Playcademy] Manifest validation failed')
60
- }
61
-
62
- const manifestPath = path.resolve(outDir, 'playcademy.manifest.json')
63
- const manifestJson = JSON.stringify(validation.data, null, 2)
64
-
65
- await fs.writeFile(manifestPath, manifestJson)
66
-
67
- try {
68
- const stats = await fs.stat(manifestPath)
69
- buildOutputs.manifestPath = path.relative(config.root, manifestPath)
70
- buildOutputs.manifestSizeKb = (stats.size / 1024).toFixed(2)
71
- } catch (statError) {
72
- config.logger.warn(
73
- `[Playcademy] Could not get stats for manifest file: ${statError}`,
74
- )
75
- }
76
- }
77
-
78
- async function createOutputZipArchive(
79
- config: ResolvedConfig,
80
- outDir: string,
81
- buildOutputs: PlaycademyOutputData,
82
- ) {
83
- const projectRoot = path.resolve(config.root)
84
- const projectName = path.basename(projectRoot)
85
- const playcademyDir = path.resolve(projectRoot, '.playcademy')
86
-
87
- await fs.mkdir(playcademyDir, { recursive: true })
88
-
89
- const zipName = `${projectName}.zip`
90
- const zipOutPath = path.resolve(playcademyDir, zipName)
91
-
92
- const output = createWriteStream(zipOutPath)
93
- const archive = archiver('zip', {
94
- zlib: { level: 9 },
95
- })
96
-
97
- await new Promise<void>((resolve, reject) => {
98
- output.on('close', () => {
99
- buildOutputs.zipPath = path.relative(config.root, zipOutPath)
100
- buildOutputs.zipSizeKb = (archive.pointer() / 1024).toFixed(2)
101
- resolve()
102
- })
103
- output.on('error', reject)
104
- archive.pipe(output)
105
- archive.directory(outDir, false)
106
- archive.finalize()
107
- })
108
- }
109
-
110
- function performPlaycademyLogging(
111
- config: ResolvedConfig,
112
- buildOutputs: PlaycademyOutputData,
113
- ) {
114
- if (!buildOutputs.manifestPath && !buildOutputs.zipSizeKb) {
115
- return
116
- }
117
-
118
- config.logger.info('') // newline
119
- config.logger.info(pc.magenta('[Playcademy]'))
120
-
121
- if (buildOutputs.manifestPath && buildOutputs.manifestSizeKb) {
122
- const dir = path.dirname(buildOutputs.manifestPath)
123
- const file = path.basename(buildOutputs.manifestPath)
124
- const uncoloredPathLength =
125
- (dir === '.' ? 0 : dir.length + 1) + file.length
126
- const coloredPath = `${pc.dim(dir === '.' ? '' : dir + '/')}${pc.green(file)}`
127
-
128
- const formattedNumber = formatNumberWithCommas(
129
- buildOutputs.manifestSizeKb!,
130
- )
131
- const sizeString = `${formattedNumber} kB`
132
- const formattedSize = pc.bold(pc.yellow(sizeString))
133
-
134
- const paddingNeeded = Math.max(
135
- 2,
136
- LOG_LINE_TOTAL_WIDTH - uncoloredPathLength - sizeString.length,
137
- )
138
- const paddingSpaces = ' '.repeat(paddingNeeded)
139
-
140
- config.logger.info(`${coloredPath}${paddingSpaces}${formattedSize}`)
141
- }
142
-
143
- if (buildOutputs.zipPath && buildOutputs.zipSizeKb) {
144
- let dir = path.dirname(buildOutputs.zipPath)
145
- const file = path.basename(buildOutputs.zipPath)
146
- if (dir === '.') dir = ''
147
- const uncoloredPathLength = (dir ? dir.length + 1 : 0) + file.length
148
- const coloredPath = `${dir ? pc.dim(dir + '/') : ''}${pc.green(file)}`
149
-
150
- const formattedNumber = formatNumberWithCommas(buildOutputs.zipSizeKb!)
151
- const sizeString = `${formattedNumber} kB`
152
- const formattedSize = pc.bold(pc.yellow(sizeString))
153
-
154
- const paddingNeeded = Math.max(
155
- 2,
156
- LOG_LINE_TOTAL_WIDTH - uncoloredPathLength - sizeString.length,
157
- )
158
- const paddingSpaces = ' '.repeat(paddingNeeded)
159
-
160
- config.logger.info(`${coloredPath}${paddingSpaces}${formattedSize}`)
161
- }
162
-
163
- config.logger.info('') // newline
164
- }
165
-
166
- export function playcademy(options: PlaycademyPluginOptions = {}): Plugin {
167
- let viteConfig: ResolvedConfig
168
- let currentBuildOutputs: PlaycademyOutputData = {}
169
-
170
- const finalOptions = {
171
- bootMode: options.bootMode ?? 'iframe',
172
- entryPoint: options.entryPoint ?? 'index.html',
173
- styles: options.styles ?? [],
174
- engine: options.engine ?? 'custom',
175
- autoZip: process.env.CI === 'true' ? false : (options.autoZip ?? false),
176
- }
177
-
178
- return {
179
- name: 'vite-plugin-playcademy',
180
-
181
- config(userConfig) {
182
- if (userConfig.base === undefined) {
183
- return {
184
- base: './',
185
- }
186
- }
187
- return {}
188
- },
189
-
190
- configResolved(resolvedConfig) {
191
- viteConfig = resolvedConfig
192
- currentBuildOutputs = {}
193
- },
194
-
195
- async writeBundle() {
196
- const outDir =
197
- viteConfig.build.outDir || path.join(process.cwd(), 'dist')
198
-
199
- try {
200
- await generatePlaycademyManifest(
201
- viteConfig,
202
- finalOptions,
203
- outDir,
204
- currentBuildOutputs,
205
- )
206
- if (finalOptions.autoZip) {
207
- await createOutputZipArchive(
208
- viteConfig,
209
- outDir,
210
- currentBuildOutputs,
211
- )
212
- }
213
- } catch (error) {
214
- if (
215
- error instanceof Error &&
216
- error.message.includes('[Playcademy]')
217
- ) {
218
- viteConfig.logger.error(error.message)
219
- } else {
220
- viteConfig.logger.error(
221
- `[Playcademy] An unexpected error occurred during writeBundle: ${error instanceof Error ? error.message : String(error)}`,
222
- )
223
- }
224
- }
225
- },
226
-
227
- closeBundle() {
228
- performPlaycademyLogging(viteConfig, currentBuildOutputs)
229
- },
230
- }
231
- }
package/sst-env.d.ts DELETED
@@ -1,9 +0,0 @@
1
- /* This file is auto-generated by SST. Do not edit. */
2
- /* tslint:disable */
3
- /* eslint-disable */
4
- /* deno-fmt-ignore-file */
5
-
6
- /// <reference path="../../sst-env.d.ts" />
7
-
8
- import "sst"
9
- export {}
package/tsconfig.json DELETED
@@ -1,28 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- // Environment setup & latest features
4
- "lib": ["ESNext"],
5
- "target": "ESNext",
6
- "module": "ESNext",
7
- "moduleDetection": "force",
8
- "jsx": "react-jsx",
9
- "allowJs": true,
10
-
11
- // Bundler mode
12
- "moduleResolution": "bundler",
13
- "allowImportingTsExtensions": true,
14
- "verbatimModuleSyntax": true,
15
- "noEmit": true,
16
-
17
- // Best practices
18
- "strict": true,
19
- "skipLibCheck": true,
20
- "noFallthroughCasesInSwitch": true,
21
- "noUncheckedIndexedAccess": true,
22
-
23
- // Some stricter flags (disabled by default)
24
- "noUnusedLocals": false,
25
- "noUnusedParameters": false,
26
- "noPropertyAccessFromIndexSignature": false
27
- }
28
- }
@@ -1,13 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "noEmit": false,
5
- "emitDeclarationOnly": true,
6
- "declaration": true,
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "skipLibCheck": true
10
- },
11
- "include": ["src/**/*.ts"],
12
- "exclude": ["node_modules", "**/*.test.ts"]
13
- }