diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000000..35b514ef84c --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,43 @@ +version: 2.1 + +workflows: + version: 2 + build-and-deploy: + jobs: + - build: + filters: + branches: + only: + - current + +jobs: + build: + docker: + - image: cimg/node:20.12 + steps: + - checkout + - restore_cache: + name: Restore pnpm Package Cache + keys: + - pnpm-packages-{{ checksum "pnpm-lock.yaml" }} + - run: + name: Install pnpm package manager + command: | + corepack enable --install-directory ~/bin + corepack prepare pnpm@latest-8 --activate + pnpm config set store-dir .pnpm-store + - run: + name: Install Dependencies + command: | + pnpm install + - save_cache: + name: Save pnpm Package Cache + key: pnpm-packages-{{ checksum "pnpm-lock.yaml" }} + paths: + - .pnpm-store + - run: + name: Build bundle + command: pnpm run build:bundle + - run: + name: Copy to bucket + command: npm run bundle:upload diff --git a/package.json b/package.json index aa9d5955e8c..7a12076cd84 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "build:e2e": "pnpm e2e:build", "build:performance-studio": "pnpm perf:studio:build", "build:test-studio": "pnpm build --filter=sanity-test-studio", + "bundle:upload": "node -r esbuild-register scripts/uploadBundles", "check": "npm-run-all build --parallel check:*", "check:deps": "pnpm --recursive --parallel exec depcheck", "check:format": "prettier . --check", @@ -97,6 +98,7 @@ "@babel/preset-react": "^7.24.1", "@babel/preset-typescript": "^7.24.1", "@bjoerge/mutiny": "^0.5.3", + "@google-cloud/storage": "^7.11.0", "@jest/globals": "^29.7.0", "@playwright/test": "1.41.2", "@repo/package.config": "workspace:*", diff --git a/packages/@repo/shared-modules.bundle/package.bundle.ts b/packages/@repo/shared-modules.bundle/package.bundle.ts index 8163df87d45..5ff43a7537e 100644 --- a/packages/@repo/shared-modules.bundle/package.bundle.ts +++ b/packages/@repo/shared-modules.bundle/package.bundle.ts @@ -6,13 +6,16 @@ export default defineConfig(() => { return mergeConfig(defaultConfig, { build: { lib: { + // NOTE: IF ANY OF THIS CHANGES MAKE SURE TO UPDATE `scripts/uploadBundles.ts` entry: { - 'react': './node_modules/react/cjs/react.production.min.js', - 'react-dom': './node_modules/react-dom/cjs/react-dom.production.min.js', - 'react-dom_server': + 'react/index': './node_modules/react/cjs/react.production.min.js', + 'react-dom/index': './node_modules/react-dom/cjs/react-dom.production.min.js', + 'react-dom/client': './node_modules/react-dom/cjs/react-dom.production.min.js', + 'react-dom/server': './node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.min.js', - 'react_jsx-runtime': './node_modules/react/cjs/react-jsx-runtime.production.min.js', - 'styled-components': './node_modules/styled-components/dist/styled-components.esm.js', + 'react/jsx-runtime': './node_modules/react/cjs/react-jsx-runtime.production.min.js', + 'styled-components/index': + './node_modules/styled-components/dist/styled-components.esm.js', }, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c83607eecce..3def0d2894c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,6 +31,9 @@ importers: '@bjoerge/mutiny': specifier: ^0.5.3 version: 0.5.3 + '@google-cloud/storage': + specifier: ^7.11.0 + version: 7.11.0 '@jest/globals': specifier: ^29.7.0 version: 29.7.0 @@ -4221,6 +4224,48 @@ packages: /@floating-ui/utils@0.2.1: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + /@google-cloud/paginator@5.0.0: + resolution: {integrity: sha512-87aeg6QQcEPxGCOthnpUjvw4xAZ57G7pL8FS0C4e/81fr3FjkpUpibf1s2v5XGyGhUVGF4Jfg7yEcxqn2iUw1w==} + engines: {node: '>=14.0.0'} + dependencies: + arrify: 2.0.1 + extend: 3.0.2 + dev: true + + /@google-cloud/projectify@4.0.0: + resolution: {integrity: sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==} + engines: {node: '>=14.0.0'} + dev: true + + /@google-cloud/promisify@4.0.0: + resolution: {integrity: sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==} + engines: {node: '>=14'} + dev: true + + /@google-cloud/storage@7.11.0: + resolution: {integrity: sha512-W+OPOCgq7a3aAMANALbJAlEnpMV9fy681JWIm7dYe5W/+nRhq/UvA477TJT5/oPNA5DgiAdMEdiitdoLpZqhJg==} + engines: {node: '>=14'} + dependencies: + '@google-cloud/paginator': 5.0.0 + '@google-cloud/projectify': 4.0.0 + '@google-cloud/promisify': 4.0.0 + abort-controller: 3.0.0 + async-retry: 1.3.3 + duplexify: 4.1.3 + fast-xml-parser: 4.3.6 + gaxios: 6.5.0 + google-auth-library: 9.9.0 + html-entities: 2.5.2 + mime: 3.0.0 + p-limit: 3.1.0 + retry-request: 7.0.2 + teeny-request: 9.0.0 + uuid: 8.3.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} dev: true @@ -7471,6 +7516,10 @@ packages: '@types/node': 18.19.31 dev: true + /@types/caseless@0.12.5: + resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==} + dev: true + /@types/configstore@5.0.1: resolution: {integrity: sha512-c/QCznvk7bLKGhHETj29rqKufui3jaAxjBhK4R2zUrMG5UG0qTwfWYxBoUbH8JCyDjdCWMIxPJ7/Fdz1UcAnWg==} dev: true @@ -7741,6 +7790,15 @@ packages: '@types/prismjs': 1.26.3 dev: true + /@types/request@2.48.12: + resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} + dependencies: + '@types/caseless': 0.12.5 + '@types/node': 18.19.31 + '@types/tough-cookie': 4.0.5 + form-data: 2.5.1 + dev: true + /@types/resolve-from@4.0.0: resolution: {integrity: sha512-LjkxahYnTBr75YRCEI/FQnQVfP4fP69koNW+3bmSkZuiSCkXkTJpfl7SPcZ4biXfmZHduoVLElP4VWBhex+0zQ==} dev: true @@ -8235,7 +8293,6 @@ packages: engines: {node: '>=6.5'} dependencies: event-target-shim: 5.0.1 - dev: false /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -8634,6 +8691,12 @@ packages: tslib: 2.6.2 dev: false + /async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + dependencies: + retry: 0.13.1 + dev: true + /async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} @@ -8833,6 +8896,10 @@ packages: dependencies: require-from-string: 2.0.2 + /bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + dev: true + /binary-extensions@1.13.1: resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} engines: {node: '>=0.10.0'} @@ -8991,6 +9058,10 @@ packages: engines: {node: '>=8.0.0'} dev: false + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: true + /buffer-fill@1.0.0: resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} dev: false @@ -10426,7 +10497,6 @@ packages: inherits: 2.0.4 readable-stream: 3.6.2 stream-shift: 1.0.3 - dev: false /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -10436,6 +10506,12 @@ packages: engines: {node: '>=6.0.0'} dev: true + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -11306,7 +11382,6 @@ packages: /event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - dev: false /event-target-shim@6.0.2: resolution: {integrity: sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==} @@ -11503,7 +11578,6 @@ packages: /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false /external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} @@ -11565,6 +11639,13 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true + /fast-xml-parser@4.3.6: + resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==} + hasBin: true + dependencies: + strnum: 1.0.5 + dev: true + /fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: @@ -11860,6 +11941,15 @@ packages: cross-spawn: 7.0.3 signal-exit: 4.1.0 + /form-data@2.5.1: + resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -12013,6 +12103,31 @@ packages: wide-align: 1.1.5 dev: true + /gaxios@6.5.0: + resolution: {integrity: sha512-R9QGdv8j4/dlNoQbX3hSaK/S0rkMijqjVvW3YM06CoBdbU/VdKd159j4hePpng0KuE6Lh6JJ7UdmVGJZFcAG1w==} + engines: {node: '>=14'} + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.4 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /gcp-metadata@6.1.0: + resolution: {integrity: sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==} + engines: {node: '>=14'} + dependencies: + gaxios: 6.5.0 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -12488,6 +12603,21 @@ packages: through2: 0.6.5 dev: false + /google-auth-library@9.9.0: + resolution: {integrity: sha512-9l+zO07h1tDJdIHN74SpnWIlNR+OuOemXlWJlLP9pXy6vFtizgpEzMuwJa4lqY9UAdiAv5DVd5ql0Am916I+aA==} + engines: {node: '>=14'} + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.5.0 + gcp-metadata: 6.1.0 + gtoken: 7.1.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -12519,6 +12649,17 @@ packages: resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} requiresBuild: true + /gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + dependencies: + gaxios: 6.5.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /gunzip-maybe@1.4.2: resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==} hasBin: true @@ -12699,6 +12840,10 @@ packages: dependencies: whatwg-encoding: 3.1.1 + /html-entities@2.5.2: + resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + dev: true + /html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true @@ -14180,6 +14325,12 @@ packages: doc-path: 4.1.1 dev: false + /json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + dependencies: + bignumber.js: 9.1.2 + dev: true + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true @@ -14274,6 +14425,21 @@ packages: object.values: 1.2.0 dev: true + /jwa@2.0.0: + resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: true + + /jws@4.0.0: + resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + dependencies: + jwa: 2.0.0 + safe-buffer: 5.2.1 + dev: true + /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: @@ -15003,6 +15169,12 @@ packages: engines: {node: '>=4'} hasBin: true + /mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + dev: true + /mimic-fn@1.2.0: resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} engines: {node: '>=4'} @@ -15381,6 +15553,18 @@ packages: whatwg-url: 5.0.0 dev: true + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + /node-gyp@10.1.0: resolution: {integrity: sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==} engines: {node: ^16.14.0 || >=18.0.0} @@ -17324,11 +17508,28 @@ packages: engines: {node: '>=0.12'} dev: true + /retry-request@7.0.2: + resolution: {integrity: sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==} + engines: {node: '>=14'} + dependencies: + '@types/request': 2.48.12 + extend: 3.0.2 + teeny-request: 9.0.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} dev: true + /retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + dev: true + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -18114,9 +18315,14 @@ packages: stream-shift: 1.0.3 dev: false + /stream-events@1.0.5: + resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} + dependencies: + stubs: 3.0.0 + dev: true + /stream-shift@1.0.3: resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} - dev: false /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} @@ -18296,6 +18502,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + /strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + dev: true + /strong-log-transformer@2.1.0: resolution: {integrity: sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==} engines: {node: '>=4'} @@ -18306,6 +18516,10 @@ packages: through: 2.3.8 dev: true + /stubs@3.0.0: + resolution: {integrity: sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==} + dev: true + /style-mod@4.1.2: resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} dev: false @@ -18511,6 +18725,20 @@ packages: yallist: 4.0.0 dev: true + /teeny-request@9.0.0: + resolution: {integrity: sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==} + engines: {node: '>=14'} + dependencies: + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + node-fetch: 2.7.0 + stream-events: 1.0.5 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /temp-dir@1.0.0: resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} engines: {node: '>=4'} diff --git a/scripts/uploadBundles.ts b/scripts/uploadBundles.ts new file mode 100644 index 00000000000..16399922a99 --- /dev/null +++ b/scripts/uploadBundles.ts @@ -0,0 +1,184 @@ +import {readdir, readFile, stat, writeFile} from 'node:fs/promises' +import path from 'node:path' + +// eslint-disable-next-line import/no-extraneous-dependencies +import {Storage, type UploadOptions} from '@google-cloud/storage' + +import {readEnv} from './utils/envVars' + +type KnownEnvVar = 'GOOGLE_PROJECT_ID' | 'GCLOUD_SERVICE_KEY' | 'GCLOUD_BUCKET' + +const storage = new Storage({ + projectId: readEnv('GOOGLE_PROJECT_ID'), + credentials: JSON.parse(readEnv('GCLOUD_SERVICE_KEY')), +}) + +const bucket = storage.bucket(readEnv('GCLOUD_BUCKET')) + +const corePkgs = ['sanity', '@sanity/vision'] as const +const sharedPkgs = ['react', 'react-dom', 'styled-components'] as const + +const appVersion = 'v1' + +/** + * Replaces all slashes with double underscores + */ +function cleanDirName(dirName: string) { + return dirName.replace(/\//g, '__') +} + +/** + * Recursively iterate through a directory and yield all files + * @param directory - The directory to iterate + */ +async function* getFiles(directory: string): AsyncGenerator { + for (const file of await readdir(directory)) { + const fullPath = path.join(directory, file) + const stats = await stat(fullPath) + + if (stats.isDirectory()) { + yield* getFiles(fullPath) + } + + if (stats.isFile()) { + yield fullPath + } + } +} + +async function copyPackages() { + console.log('**Copying Core packages**') + + const packageVersions = new Map() + + // First we iterate through each core package located in `packages/` + for (const pkg of corePkgs) { + console.log(`Copying files from ${pkg}`) + + const packageJson = JSON.parse(await readFile(`packages/${pkg}/package.json`, 'utf8')) + + const {version} = packageJson + packageVersions.set(pkg, version) + + // Convert slashes to double underscores + // Needed for `@sanity/vision` + const cleanDir = cleanDirName(pkg) + + for await (const filePath of getFiles(`packages/${pkg}/dist`)) { + try { + const fileName = path.basename(filePath) + const options: UploadOptions = { + destination: `modules/${appVersion}/${cleanDir}/${version}/bare/${fileName}`, + gzip: true, + contentType: 'application/javascript', + } + + // Upload files to the proper bucket destination + await bucket.upload(filePath, options) + } catch (error) { + throw new Error(`Failed to copy files from ${pkg}`, {cause: error}) + } + } + + console.log(`Completed copy for directory ${pkg}`) + } + + console.log('**Copying shared dependencies**') + + // Shared dependencies are in `packages/@repo/shared-modules.bundle` + // with built files in `packages/@repo/shared-modules.bundle/dist/` + for (const pkg of sharedPkgs) { + console.log(`Copying files from ${pkg}`) + + const packageJson = JSON.parse( + await readFile( + `packages/@repo/shared-modules.bundle/node_modules/${pkg}/package.json`, + 'utf8', + ), + ) + const {version} = packageJson + + packageVersions.set(pkg, version) + + for await (const filePath of getFiles(`packages/@repo/shared-modules.bundle/dist/${pkg}`)) { + try { + const fileName = path.basename(filePath) + const options: UploadOptions = { + destination: `modules/${appVersion}/${pkg}/${version}/bare/${fileName}`, + gzip: true, + contentType: 'application/javascript', + } + + await bucket.upload(filePath, options) + } catch (error) { + throw new Error(`Failed to copy files from ${pkg}`, {cause: error}) + } + } + + console.log(`Completed copy for directory ${pkg}`) + } + + return packageVersions +} + +interface Manifest { + packages: Record> +} + +async function updateManifest(newVersions: Map) { + console.log('**Updating manifest**') + + let existingManifest: Manifest = {packages: {}} + + try { + // Download the manifest + const buffer = await bucket.file('modules/v1/manifest-v1.json').download() + existingManifest = JSON.parse(buffer.toString()) + } catch (error) { + console.log('Existing manifest not found', error) + } + + // Add the new version to the manifest + const newManifest = Array.from(newVersions).reduce((initial, [key, value]) => { + const dirName = cleanDirName(key) + + return { + ...initial, + packages: { + ...initial.packages, + [dirName]: { + ...initial.packages[dirName], + default: value, + }, + }, + } + }, existingManifest) + + await writeFile('./manifest-v1.json', JSON.stringify(newManifest), {encoding: 'utf-8'}) + + try { + const options = { + destination: 'modules/v1/manifest-v1.json', + contentType: 'application/json', + } + + await bucket.upload('manifest-v1.json', options) + } catch (error) { + throw new Error('Error copying manifest file', {cause: error}) + } +} + +async function uploadBundles() { + // Copy all the bundles + const pkgVersions = await copyPackages() + console.log('**Completed copying all files** ✅') + + // Update the manifest json file + await updateManifest(pkgVersions) + console.log('**Completed updating manifest** ✅') +} + +uploadBundles().catch((err) => { + console.error(err) + process.exit(1) +})