@webiny/project 0.0.0-unstable.df7a8bb475 → 5.45.0-beta.0
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.
- package/defineExtension/defineApiExtension.js +2 -8
- package/defineExtension/defineApiExtension.js.map +1 -1
- package/defineExtension/zodTypes/zodSrcPath.d.ts +1 -0
- package/defineExtension/zodTypes/zodSrcPath.js +7 -14
- package/defineExtension/zodTypes/zodSrcPath.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/package.json +15 -15
- package/services/InitProjectSdkService/registerDecorators.js +2 -2
- package/services/InitProjectSdkService/registerDecorators.js.map +1 -1
- package/services/InitProjectSdkService/registerHooks.js +2 -2
- package/services/InitProjectSdkService/registerHooks.js.map +1 -1
- package/services/InitProjectSdkService/registerImplementations.js +2 -2
- package/services/InitProjectSdkService/registerImplementations.js.map +1 -1
- package/services/InitProjectSdkService/registerPulumiExtensions.js +2 -2
- package/services/InitProjectSdkService/registerPulumiExtensions.js.map +1 -1
- package/services/InstallExtensionService/InstallExtensionService.d.ts +1 -1
- package/services/InstallExtensionService/InstallExtensionService.js +3 -3
- package/services/InstallExtensionService/InstallExtensionService.js.map +1 -1
- package/services/InstallExtensionService/mergePackageJson.js +4 -4
- package/services/InstallExtensionService/mergePackageJson.js.map +1 -1
- package/services/ListAppLambdaFunctionsService/ListAppLambdaFunctionsService.js +1 -1
- package/services/ListAppLambdaFunctionsService/ListAppLambdaFunctionsService.js.map +1 -1
- package/utils/ExtensionSrcResolver.d.ts +33 -0
- package/utils/ExtensionSrcResolver.js +119 -0
- package/utils/ExtensionSrcResolver.js.map +1 -0
- package/utils/index.d.ts +1 -1
- package/utils/index.js +1 -1
- package/utils/index.js.map +1 -1
- package/utils/ImplPathResolver.d.ts +0 -10
- package/utils/ImplPathResolver.js +0 -27
- package/utils/ImplPathResolver.js.map +0 -1
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { Node, Project } from "ts-morph";
|
|
3
3
|
import { defineExtension } from "./index.js";
|
|
4
4
|
import { zodSrcPath } from "./zodTypes/zodSrcPath.js";
|
|
5
|
+
import { ExtensionSrcResolver } from "../utils/index.js";
|
|
5
6
|
import path from "path";
|
|
6
7
|
import crypto from "crypto";
|
|
7
8
|
export const defineApiExtension = params => defineExtension({
|
|
@@ -30,14 +31,7 @@ export const defineApiExtension = params => defineExtension({
|
|
|
30
31
|
} = params;
|
|
31
32
|
|
|
32
33
|
// Resolve to absolute path for file operations
|
|
33
|
-
|
|
34
|
-
if (extensionFilePath.startsWith("/extensions/")) {
|
|
35
|
-
// Resolve from project root
|
|
36
|
-
absoluteExtensionFilePath = ctx.project.paths.rootFolder.join(extensionFilePath).toString();
|
|
37
|
-
} else {
|
|
38
|
-
// Treat as absolute path
|
|
39
|
-
absoluteExtensionFilePath = extensionFilePath;
|
|
40
|
-
}
|
|
34
|
+
const absoluteExtensionFilePath = ExtensionSrcResolver.resolvePath(extensionFilePath, ctx.project);
|
|
41
35
|
const extensionFileName = path.basename(absoluteExtensionFilePath);
|
|
42
36
|
|
|
43
37
|
// 1. Export name is always the file name without extension.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["z","Node","Project","defineExtension","zodSrcPath","path","crypto","defineApiExtension","params","type","tags","runtimeContext","appName","description","multiple","paramsSchema","project","object","src","abstraction","exportName","string","optional","build","ctx","extensionsTsFilePath","paths","workspaceFolder","join","toString","extensionFilePath","absoluteExtensionFilePath","
|
|
1
|
+
{"version":3,"names":["z","Node","Project","defineExtension","zodSrcPath","ExtensionSrcResolver","path","crypto","defineApiExtension","params","type","tags","runtimeContext","appName","description","multiple","paramsSchema","project","object","src","abstraction","exportName","string","optional","build","ctx","extensionsTsFilePath","paths","workspaceFolder","join","toString","extensionFilePath","absoluteExtensionFilePath","resolvePath","extensionFileName","basename","parse","name","hash","createHash","update","digest","exportNameAlias","slice","importPath","relative","dirname","replace","addSourceFileAtPath","source","getSourceFileOrThrow","existingImportDeclaration","getImportDeclaration","index","importDeclarations","getImportDeclarations","length","last","getChildIndex","extensionProject","extensionSource","hasDefaultExport","getDefaultExportSymbol","undefined","insertImportDeclaration","defaultImport","moduleSpecifier","namedImports","alias","pluginsArray","getFirstDescendant","node","isArrayLiteralExpression","addElement","contextPluginImportPath","existingContextPluginImport","save"],"sources":["defineApiExtension.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { Node, Project, ArrayLiteralExpression } from \"ts-morph\";\nimport { Abstraction } from \"@webiny/di\";\nimport { defineExtension } from \"~/defineExtension/index.js\";\nimport { zodSrcPath } from \"~/defineExtension/zodTypes/zodSrcPath.js\";\nimport { ExtensionSrcResolver } from \"~/utils/index.js\";\nimport path from \"path\";\nimport crypto from \"crypto\";\n\nexport type DefineApiExtensionParams = {\n type: string;\n description?: string;\n abstraction?: Abstraction<any>;\n};\n\nexport const defineApiExtension = (params: DefineApiExtensionParams) =>\n defineExtension({\n type: params.type,\n tags: { runtimeContext: \"app-build\", appName: \"api\" },\n description: params.description,\n multiple: true,\n paramsSchema: ({ project }) => {\n return z.object({\n src: zodSrcPath({ project, abstraction: params.abstraction }),\n exportName: z.string().optional()\n });\n },\n async build(params, ctx) {\n const extensionsTsFilePath = ctx.project.paths.workspaceFolder\n .join(\"apps\", \"api\", \"graphql\", \"src\", \"extensions.ts\")\n .toString();\n\n const { src: extensionFilePath } = params;\n\n // Resolve to absolute path for file operations\n const absoluteExtensionFilePath = ExtensionSrcResolver.resolvePath(\n extensionFilePath,\n ctx.project\n );\n\n const extensionFileName = path.basename(absoluteExtensionFilePath);\n\n // 1. Export name is always the file name without extension.\n const exportName = params.exportName ?? path.parse(extensionFileName).name;\n\n // 2. Alias name is \"ApiExtension_\" + hash of the file path. This way we\n // avoid potential naming conflicts and keep the identifier constant.\n const hash = crypto.createHash(\"sha256\").update(extensionFilePath).digest(\"hex\");\n const exportNameAlias = `ApiExtension_${hash.slice(-10)}`;\n\n // 3. Calculate import path relative to `extensions.ts` file.\n const importPath = path\n .relative(path.dirname(extensionsTsFilePath), absoluteExtensionFilePath)\n .replace(/\\.tsx?$/, \".js\");\n\n const project = new Project();\n project.addSourceFileAtPath(extensionsTsFilePath);\n\n const source = project.getSourceFileOrThrow(extensionsTsFilePath);\n\n const existingImportDeclaration = source.getImportDeclaration(importPath);\n if (existingImportDeclaration) {\n return;\n }\n\n let index = 1;\n\n const importDeclarations = source.getImportDeclarations();\n if (importDeclarations.length) {\n const last = importDeclarations[importDeclarations.length - 1];\n index = last.getChildIndex() + 1;\n }\n\n // Check if the file has a default export using AST parsing.\n const extensionProject = new Project();\n extensionProject.addSourceFileAtPath(absoluteExtensionFilePath);\n const extensionSource =\n extensionProject.getSourceFileOrThrow(absoluteExtensionFilePath);\n const hasDefaultExport = extensionSource.getDefaultExportSymbol() !== undefined;\n\n // Support both default and named exports.\n if (hasDefaultExport) {\n source.insertImportDeclaration(index, {\n defaultImport: exportNameAlias,\n moduleSpecifier: importPath\n });\n } else {\n source.insertImportDeclaration(index, {\n namedImports: [{ name: exportName, alias: exportNameAlias }],\n moduleSpecifier: importPath\n });\n }\n\n const pluginsArray = source.getFirstDescendant(node =>\n Node.isArrayLiteralExpression(node)\n ) as ArrayLiteralExpression;\n\n pluginsArray.addElement(\n `\\ncreateContextPlugin(ctx => {\\n\\tregisterExtension(ctx.container, ${exportNameAlias});\\n})`\n );\n\n {\n let index = 1;\n\n const importDeclarations = source.getImportDeclarations();\n if (importDeclarations.length) {\n const last = importDeclarations[importDeclarations.length - 1];\n index = last.getChildIndex() + 1;\n }\n\n const contextPluginImportPath = \"@webiny/api/plugins/ContextPlugin\";\n const existingContextPluginImport =\n source.getImportDeclaration(contextPluginImportPath);\n if (!existingContextPluginImport) {\n source.insertImportDeclaration(index, {\n namedImports: [\"createContextPlugin\"],\n moduleSpecifier: contextPluginImportPath\n });\n }\n }\n\n await source.save();\n }\n });\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,6 +4,7 @@ import { type IProjectModel } from "../../abstractions/models/index.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* TypeScript type for source paths.
|
|
6
6
|
* - `/extensions/${string}` - resolves from project root
|
|
7
|
+
* - `@/${string}` or other tsconfig aliases - resolves using tsconfig.json paths
|
|
7
8
|
* - string (absolute path) - treated as absolute path
|
|
8
9
|
*/
|
|
9
10
|
export type SrcPath = `/extensions/${string}` | string;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Metadata } from "@webiny/di";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import fs from "fs";
|
|
5
4
|
import { ProjectError } from "../../ProjectError.js";
|
|
6
|
-
import {
|
|
5
|
+
import { ExtensionSrcResolver } from "../../utils/index.js";
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* TypeScript type for source paths.
|
|
10
9
|
* - `/extensions/${string}` - resolves from project root
|
|
10
|
+
* - `@/${string}` or other tsconfig aliases - resolves using tsconfig.json paths
|
|
11
11
|
* - string (absolute path) - treated as absolute path
|
|
12
12
|
*/
|
|
13
13
|
|
|
@@ -21,18 +21,10 @@ export const zodSrcPath = options => {
|
|
|
21
21
|
return str.replace(/^Symbol\(/, "").replace(/\)$/, "");
|
|
22
22
|
};
|
|
23
23
|
const tokenName = abstraction ? getTokenName(abstraction.token) : undefined;
|
|
24
|
-
const description = abstraction ? `Path to a file exporting ${tokenName}. Use "/extensions/..." to resolve from project root, or provide an absolute path.` : `Path: "/extensions/..." resolves from project root, or provide an absolute path.`;
|
|
24
|
+
const description = abstraction ? `Path to a file exporting ${tokenName}. Use "/extensions/..." to resolve from project root, "@/..." for tsconfig path aliases, or provide an absolute path.` : `Path: "/extensions/..." resolves from project root, "@/..." resolves using tsconfig path aliases, or provide an absolute path.`;
|
|
25
25
|
return z.string().describe(description).transform(val => val).superRefine(async (src, ctx) => {
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
if (src.startsWith("/extensions/")) {
|
|
29
|
-
// Resolve from project root.
|
|
30
|
-
absoluteSrcPath = project.paths.rootFolder.join(src).toString();
|
|
31
|
-
} else {
|
|
32
|
-
// Treat as absolute path.
|
|
33
|
-
absoluteSrcPath = src;
|
|
34
|
-
}
|
|
35
|
-
if (!fs.existsSync(absoluteSrcPath)) {
|
|
26
|
+
// Check if file exists using ExtensionSrcResolver.
|
|
27
|
+
if (!ExtensionSrcResolver.existsSync(src, project)) {
|
|
36
28
|
ctx.addIssue({
|
|
37
29
|
code: z.ZodIssueCode.custom,
|
|
38
30
|
message: ProjectError.formatMessage(`File not found: %s. Please check the path and try again.`, src)
|
|
@@ -42,8 +34,9 @@ export const zodSrcPath = options => {
|
|
|
42
34
|
|
|
43
35
|
// If abstraction validation is required
|
|
44
36
|
if (abstraction) {
|
|
37
|
+
const absoluteSrcPath = ExtensionSrcResolver.resolvePath(src, project);
|
|
45
38
|
const exportName = path.basename(absoluteSrcPath).replace(path.extname(absoluteSrcPath), "");
|
|
46
|
-
const exportedImplementation = await
|
|
39
|
+
const exportedImplementation = await ExtensionSrcResolver.importFromPath(src, project);
|
|
47
40
|
if (!exportedImplementation) {
|
|
48
41
|
ctx.addIssue({
|
|
49
42
|
code: z.ZodIssueCode.custom,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Metadata","z","path","
|
|
1
|
+
{"version":3,"names":["Metadata","z","path","ProjectError","ExtensionSrcResolver","zodSrcPath","options","project","abstraction","getTokenName","token","str","toString","replace","tokenName","undefined","description","string","describe","transform","val","superRefine","src","ctx","existsSync","addIssue","code","ZodIssueCode","custom","message","formatMessage","absoluteSrcPath","resolvePath","exportName","basename","extname","exportedImplementation","importFromPath","metadata","metadataName","getAbstraction","defName","isCorrectAbstraction"],"sources":["zodSrcPath.ts"],"sourcesContent":["import { type Abstraction, Metadata } from \"@webiny/di\";\nimport { z } from \"zod\";\nimport path from \"path\";\nimport { type IProjectModel } from \"~/abstractions/models/index.js\";\nimport { ProjectError } from \"~/ProjectError.js\";\nimport { ExtensionSrcResolver } from \"~/utils/index.js\";\n\n/**\n * TypeScript type for source paths.\n * - `/extensions/${string}` - resolves from project root\n * - `@/${string}` or other tsconfig aliases - resolves using tsconfig.json paths\n * - string (absolute path) - treated as absolute path\n */\nexport type SrcPath = `/extensions/${string}` | string;\n\ntype ZodSrcPathOptions = {\n project: IProjectModel;\n abstraction?: Abstraction<any>;\n};\n\nexport const zodSrcPath = (options: ZodSrcPathOptions) => {\n const { project, abstraction } = options;\n\n const getTokenName = (token: symbol) => {\n const str = token.toString();\n return str.replace(/^Symbol\\(/, \"\").replace(/\\)$/, \"\");\n };\n\n const tokenName = abstraction ? getTokenName(abstraction.token) : undefined;\n const description = abstraction\n ? `Path to a file exporting ${tokenName}. Use \"/extensions/...\" to resolve from project root, \"@/...\" for tsconfig path aliases, or provide an absolute path.`\n : `Path: \"/extensions/...\" resolves from project root, \"@/...\" resolves using tsconfig path aliases, or provide an absolute path.`;\n\n return z\n .string()\n .describe(description)\n .transform((val): SrcPath => val as SrcPath)\n .superRefine(async (src, ctx) => {\n // Check if file exists using ExtensionSrcResolver.\n if (!ExtensionSrcResolver.existsSync(src, project)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: ProjectError.formatMessage(\n `File not found: %s. Please check the path and try again.`,\n src\n )\n });\n return;\n }\n\n // If abstraction validation is required\n if (abstraction) {\n const absoluteSrcPath = ExtensionSrcResolver.resolvePath(src, project);\n const exportName = path\n .basename(absoluteSrcPath)\n .replace(path.extname(absoluteSrcPath), \"\");\n\n const exportedImplementation = await ExtensionSrcResolver.importFromPath(\n src,\n project\n );\n\n if (!exportedImplementation) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: ProjectError.formatMessage(\n `The file %s must export a class named %s or as a default export.`,\n src,\n exportName\n )\n });\n return;\n }\n\n const metadata = new Metadata(exportedImplementation);\n const metadataName = metadata.getAbstraction().toString();\n const defName = abstraction.toString();\n const isCorrectAbstraction = metadataName === defName;\n\n if (!isCorrectAbstraction) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: ProjectError.formatMessage(\n `The class %s in %s must implement the %s interface.`,\n exportName,\n src,\n tokenName || \"\"\n )\n });\n }\n }\n });\n};\n"],"mappings":"AAAA,SAA2BA,QAAQ,QAAQ,YAAY;AACvD,SAASC,CAAC,QAAQ,KAAK;AACvB,OAAOC,IAAI,MAAM,MAAM;AAEvB,SAASC,YAAY;AACrB,SAASC,oBAAoB;;AAE7B;AACA;AACA;AACA;AACA;AACA;;AAQA,OAAO,MAAMC,UAAU,GAAIC,OAA0B,IAAK;EACtD,MAAM;IAAEC,OAAO;IAAEC;EAAY,CAAC,GAAGF,OAAO;EAExC,MAAMG,YAAY,GAAIC,KAAa,IAAK;IACpC,MAAMC,GAAG,GAAGD,KAAK,CAACE,QAAQ,CAAC,CAAC;IAC5B,OAAOD,GAAG,CAACE,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAACA,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;EAC1D,CAAC;EAED,MAAMC,SAAS,GAAGN,WAAW,GAAGC,YAAY,CAACD,WAAW,CAACE,KAAK,CAAC,GAAGK,SAAS;EAC3E,MAAMC,WAAW,GAAGR,WAAW,GACzB,4BAA4BM,SAAS,uHAAuH,GAC5J,gIAAgI;EAEtI,OAAOb,CAAC,CACHgB,MAAM,CAAC,CAAC,CACRC,QAAQ,CAACF,WAAW,CAAC,CACrBG,SAAS,CAAEC,GAAG,IAAcA,GAAc,CAAC,CAC3CC,WAAW,CAAC,OAAOC,GAAG,EAAEC,GAAG,KAAK;IAC7B;IACA,IAAI,CAACnB,oBAAoB,CAACoB,UAAU,CAACF,GAAG,EAAEf,OAAO,CAAC,EAAE;MAChDgB,GAAG,CAACE,QAAQ,CAAC;QACTC,IAAI,EAAEzB,CAAC,CAAC0B,YAAY,CAACC,MAAM;QAC3BC,OAAO,EAAE1B,YAAY,CAAC2B,aAAa,CAC/B,0DAA0D,EAC1DR,GACJ;MACJ,CAAC,CAAC;MACF;IACJ;;IAEA;IACA,IAAId,WAAW,EAAE;MACb,MAAMuB,eAAe,GAAG3B,oBAAoB,CAAC4B,WAAW,CAACV,GAAG,EAAEf,OAAO,CAAC;MACtE,MAAM0B,UAAU,GAAG/B,IAAI,CAClBgC,QAAQ,CAACH,eAAe,CAAC,CACzBlB,OAAO,CAACX,IAAI,CAACiC,OAAO,CAACJ,eAAe,CAAC,EAAE,EAAE,CAAC;MAE/C,MAAMK,sBAAsB,GAAG,MAAMhC,oBAAoB,CAACiC,cAAc,CACpEf,GAAG,EACHf,OACJ,CAAC;MAED,IAAI,CAAC6B,sBAAsB,EAAE;QACzBb,GAAG,CAACE,QAAQ,CAAC;UACTC,IAAI,EAAEzB,CAAC,CAAC0B,YAAY,CAACC,MAAM;UAC3BC,OAAO,EAAE1B,YAAY,CAAC2B,aAAa,CAC/B,kEAAkE,EAClER,GAAG,EACHW,UACJ;QACJ,CAAC,CAAC;QACF;MACJ;MAEA,MAAMK,QAAQ,GAAG,IAAItC,QAAQ,CAACoC,sBAAsB,CAAC;MACrD,MAAMG,YAAY,GAAGD,QAAQ,CAACE,cAAc,CAAC,CAAC,CAAC5B,QAAQ,CAAC,CAAC;MACzD,MAAM6B,OAAO,GAAGjC,WAAW,CAACI,QAAQ,CAAC,CAAC;MACtC,MAAM8B,oBAAoB,GAAGH,YAAY,KAAKE,OAAO;MAErD,IAAI,CAACC,oBAAoB,EAAE;QACvBnB,GAAG,CAACE,QAAQ,CAAC;UACTC,IAAI,EAAEzB,CAAC,CAAC0B,YAAY,CAACC,MAAM;UAC3BC,OAAO,EAAE1B,YAAY,CAAC2B,aAAa,CAC/B,qDAAqD,EACrDG,UAAU,EACVX,GAAG,EACHR,SAAS,IAAI,EACjB;QACJ,CAAC,CAAC;MACN;IACJ;EACJ,CAAC,CAAC;AACV,CAAC","ignoreList":[]}
|
package/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export type * from "./abstractions/models/index.js";
|
|
|
9
9
|
export type { IStackOutput } from "./abstractions/features/GetAppStackOutput.js";
|
|
10
10
|
export { PackageJson } from "@webiny/build-tools/utils/PackageJson.js";
|
|
11
11
|
export { createPathResolver } from "./utils/createPathResolver.js";
|
|
12
|
+
export { ExtensionSrcResolver } from "./utils/ExtensionSrcResolver.js";
|
|
12
13
|
export { GracefulError } from "./GracefulError.js";
|
|
13
14
|
export { Wcp } from "./components/Wcp.js";
|
|
14
15
|
export { WcpProjectLicenseProvider, useWcpProjectLicense } from "./services/GetProjectConfigService/WcpProjectLicenseContext.js";
|
package/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export const getStackOutput = async appName => {
|
|
|
12
12
|
export { ProjectSdk };
|
|
13
13
|
export { PackageJson } from "@webiny/build-tools/utils/PackageJson.js";
|
|
14
14
|
export { createPathResolver } from "./utils/createPathResolver.js";
|
|
15
|
+
export { ExtensionSrcResolver } from "./utils/ExtensionSrcResolver.js";
|
|
15
16
|
export { GracefulError } from "./GracefulError.js";
|
|
16
17
|
export { Wcp } from "./components/Wcp.js";
|
|
17
18
|
export { WcpProjectLicenseProvider, useWcpProjectLicense } from "./services/GetProjectConfigService/WcpProjectLicenseContext.js";
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ProjectSdk","getProjectSdk","params","init","getStackOutput","appName","sdk","getAppStackOutput","PackageJson","createPathResolver","GracefulError","Wcp","WcpProjectLicenseProvider","useWcpProjectLicense"],"sources":["index.ts"],"sourcesContent":["import { ProjectSdk } from \"./ProjectSdk.js\";\nimport { type GetAppStackOutput } from \"~/abstractions/index.js\";\nimport { type AppName } from \"~/abstractions/types.js\";\n\nexport const getProjectSdk = (...params: Parameters<(typeof ProjectSdk)[\"init\"]>) => {\n return ProjectSdk.init(...params);\n};\n\n// A temporary convenience function to get the stack output for a specific app. We might revisit this in the\n// future and double check if there's a better way to expose this functionality.\nexport const getStackOutput = async <\n TOutput extends GetAppStackOutput.StackOutput = GetAppStackOutput.StackOutput\n>(\n appName: AppName\n) => {\n const sdk = await getProjectSdk();\n return sdk.getAppStackOutput<TOutput>(appName);\n};\n\nexport { ProjectSdk };\n\nexport type { AppName } from \"./abstractions/types.js\";\nexport type * from \"./abstractions/models/index.js\";\n\nexport type { IStackOutput } from \"~/abstractions/features/GetAppStackOutput.js\";\n\nexport { PackageJson } from \"@webiny/build-tools/utils/PackageJson.js\";\n\nexport { createPathResolver } from \"./utils/createPathResolver.js\";\n\nexport { GracefulError } from \"./GracefulError.js\";\n\nexport { Wcp } from \"./components/Wcp.js\";\nexport {\n WcpProjectLicenseProvider,\n useWcpProjectLicense\n} from \"./services/GetProjectConfigService/WcpProjectLicenseContext.js\";\n"],"mappings":"AAAA,SAASA,UAAU;AAInB,OAAO,MAAMC,aAAa,GAAGA,CAAC,GAAGC,MAA+C,KAAK;EACjF,OAAOF,UAAU,CAACG,IAAI,CAAC,GAAGD,MAAM,CAAC;AACrC,CAAC;;AAED;AACA;AACA,OAAO,MAAME,cAAc,GAAG,MAG1BC,OAAgB,IACf;EACD,MAAMC,GAAG,GAAG,MAAML,aAAa,CAAC,CAAC;EACjC,OAAOK,GAAG,CAACC,iBAAiB,CAAUF,OAAO,CAAC;AAClD,CAAC;AAED,SAASL,UAAU;AAOnB,SAASQ,WAAW,QAAQ,0CAA0C;AAEtE,SAASC,kBAAkB;AAE3B,SAASC,aAAa;AAEtB,SAASC,GAAG;AACZ,SACIC,yBAAyB,EACzBC,oBAAoB","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["ProjectSdk","getProjectSdk","params","init","getStackOutput","appName","sdk","getAppStackOutput","PackageJson","createPathResolver","ExtensionSrcResolver","GracefulError","Wcp","WcpProjectLicenseProvider","useWcpProjectLicense"],"sources":["index.ts"],"sourcesContent":["import { ProjectSdk } from \"./ProjectSdk.js\";\nimport { type GetAppStackOutput } from \"~/abstractions/index.js\";\nimport { type AppName } from \"~/abstractions/types.js\";\n\nexport const getProjectSdk = (...params: Parameters<(typeof ProjectSdk)[\"init\"]>) => {\n return ProjectSdk.init(...params);\n};\n\n// A temporary convenience function to get the stack output for a specific app. We might revisit this in the\n// future and double check if there's a better way to expose this functionality.\nexport const getStackOutput = async <\n TOutput extends GetAppStackOutput.StackOutput = GetAppStackOutput.StackOutput\n>(\n appName: AppName\n) => {\n const sdk = await getProjectSdk();\n return sdk.getAppStackOutput<TOutput>(appName);\n};\n\nexport { ProjectSdk };\n\nexport type { AppName } from \"./abstractions/types.js\";\nexport type * from \"./abstractions/models/index.js\";\n\nexport type { IStackOutput } from \"~/abstractions/features/GetAppStackOutput.js\";\n\nexport { PackageJson } from \"@webiny/build-tools/utils/PackageJson.js\";\n\nexport { createPathResolver } from \"./utils/createPathResolver.js\";\n\nexport { ExtensionSrcResolver } from \"./utils/ExtensionSrcResolver.js\";\n\nexport { GracefulError } from \"./GracefulError.js\";\n\nexport { Wcp } from \"./components/Wcp.js\";\nexport {\n WcpProjectLicenseProvider,\n useWcpProjectLicense\n} from \"./services/GetProjectConfigService/WcpProjectLicenseContext.js\";\n"],"mappings":"AAAA,SAASA,UAAU;AAInB,OAAO,MAAMC,aAAa,GAAGA,CAAC,GAAGC,MAA+C,KAAK;EACjF,OAAOF,UAAU,CAACG,IAAI,CAAC,GAAGD,MAAM,CAAC;AACrC,CAAC;;AAED;AACA;AACA,OAAO,MAAME,cAAc,GAAG,MAG1BC,OAAgB,IACf;EACD,MAAMC,GAAG,GAAG,MAAML,aAAa,CAAC,CAAC;EACjC,OAAOK,GAAG,CAACC,iBAAiB,CAAUF,OAAO,CAAC;AAClD,CAAC;AAED,SAASL,UAAU;AAOnB,SAASQ,WAAW,QAAQ,0CAA0C;AAEtE,SAASC,kBAAkB;AAE3B,SAASC,oBAAoB;AAE7B,SAASC,aAAa;AAEtB,SAASC,GAAG;AACZ,SACIC,yBAAyB,EACzBC,oBAAoB","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/project",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.45.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
"description": "An SDK for managing Webiny projects.",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@webiny/aws-sdk": "
|
|
14
|
-
"@webiny/build-tools": "
|
|
13
|
+
"@webiny/aws-sdk": "5.45.0-beta.0",
|
|
14
|
+
"@webiny/build-tools": "5.45.0-beta.0",
|
|
15
15
|
"@webiny/di": "0.2.3",
|
|
16
|
-
"@webiny/global-config": "
|
|
17
|
-
"@webiny/pulumi-sdk": "
|
|
18
|
-
"@webiny/react-properties": "
|
|
19
|
-
"@webiny/system-requirements": "
|
|
20
|
-
"@webiny/telemetry": "
|
|
21
|
-
"@webiny/utils": "
|
|
22
|
-
"@webiny/wcp": "
|
|
16
|
+
"@webiny/global-config": "5.45.0-beta.0",
|
|
17
|
+
"@webiny/pulumi-sdk": "5.45.0-beta.0",
|
|
18
|
+
"@webiny/react-properties": "5.45.0-beta.0",
|
|
19
|
+
"@webiny/system-requirements": "5.45.0-beta.0",
|
|
20
|
+
"@webiny/telemetry": "5.45.0-beta.0",
|
|
21
|
+
"@webiny/utils": "5.45.0-beta.0",
|
|
22
|
+
"@webiny/wcp": "5.45.0-beta.0",
|
|
23
23
|
"chalk": "4.1.2",
|
|
24
24
|
"chokidar": "4.0.3",
|
|
25
25
|
"ci-info": "4.4.0",
|
|
@@ -30,11 +30,12 @@
|
|
|
30
30
|
"exit-hook": "4.0.0",
|
|
31
31
|
"fast-glob": "3.3.3",
|
|
32
32
|
"find-up": "5.0.0",
|
|
33
|
+
"get-tsconfig": "4.13.6",
|
|
33
34
|
"graphql-request": "7.4.0",
|
|
34
35
|
"humanize-duration": "3.33.2",
|
|
35
|
-
"load-json-file": "
|
|
36
|
+
"load-json-file": "7.0.1",
|
|
36
37
|
"lodash": "4.17.23",
|
|
37
|
-
"minimatch": "
|
|
38
|
+
"minimatch": "10.2.2",
|
|
38
39
|
"mqtt": "5.15.0",
|
|
39
40
|
"neverthrow": "8.2.0",
|
|
40
41
|
"p-retry": "7.1.1",
|
|
@@ -47,13 +48,12 @@
|
|
|
47
48
|
"serialize-error": "12.0.0",
|
|
48
49
|
"ts-morph": "27.0.2",
|
|
49
50
|
"tsx": "4.21.0",
|
|
50
|
-
"write-json-file": "
|
|
51
|
+
"write-json-file": "7.0.0",
|
|
51
52
|
"zod": "3.25.76"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"@types/debounce": "1.2.4",
|
|
55
56
|
"@types/humanize-duration": "3.27.4",
|
|
56
|
-
"@types/jsdom": "^21.1.7",
|
|
57
57
|
"@types/lodash": "4.17.23",
|
|
58
58
|
"@types/react-test-renderer": "18.3.1",
|
|
59
59
|
"@types/read-json-sync": "2.0.3",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"access": "public",
|
|
76
76
|
"directory": "dist"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "b85c33cfbe7c02c130445c918d913ef4b2c09cb2"
|
|
79
79
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionSrcResolver } from "../../utils/index.js";
|
|
2
2
|
import { ProjectDecorator as ProjectDecoratorExt } from "../../extensions/ProjectDecorator.js";
|
|
3
3
|
export const registerDecorators = async (container, projectExtensions, project) => {
|
|
4
4
|
const projectDecorators = [...projectExtensions.extensionsByType(ProjectDecoratorExt)];
|
|
5
5
|
for (const projectDecorator of projectDecorators) {
|
|
6
|
-
const projectDecoratorImpl = await
|
|
6
|
+
const projectDecoratorImpl = await ExtensionSrcResolver.importFromPath(projectDecorator.params.src, project);
|
|
7
7
|
container.registerDecorator(projectDecoratorImpl);
|
|
8
8
|
}
|
|
9
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["ExtensionSrcResolver","ProjectDecorator","ProjectDecoratorExt","registerDecorators","container","projectExtensions","project","projectDecorators","extensionsByType","projectDecorator","projectDecoratorImpl","importFromPath","params","src","registerDecorator"],"sources":["registerDecorators.ts"],"sourcesContent":["import { type IProjectModel } from \"~/abstractions/models/index.js\";\nimport { type IProjectConfigModel } from \"~/abstractions/models/index.js\";\nimport { Container } from \"@webiny/di\";\nimport { ExtensionSrcResolver } from \"~/utils/index.js\";\nimport { ProjectDecorator as ProjectDecoratorExt } from \"~/extensions/ProjectDecorator.js\";\n\nexport const registerDecorators = async (\n container: Container,\n projectExtensions: IProjectConfigModel,\n project: IProjectModel\n) => {\n const projectDecorators = [...projectExtensions.extensionsByType(ProjectDecoratorExt)];\n\n for (const projectDecorator of projectDecorators) {\n const projectDecoratorImpl = await ExtensionSrcResolver.importFromPath(\n projectDecorator.params.src,\n project\n );\n container.registerDecorator(projectDecoratorImpl);\n }\n};\n"],"mappings":"AAGA,SAASA,oBAAoB;AAC7B,SAASC,gBAAgB,IAAIC,mBAAmB;AAEhD,OAAO,MAAMC,kBAAkB,GAAG,MAAAA,CAC9BC,SAAoB,EACpBC,iBAAsC,EACtCC,OAAsB,KACrB;EACD,MAAMC,iBAAiB,GAAG,CAAC,GAAGF,iBAAiB,CAACG,gBAAgB,CAACN,mBAAmB,CAAC,CAAC;EAEtF,KAAK,MAAMO,gBAAgB,IAAIF,iBAAiB,EAAE;IAC9C,MAAMG,oBAAoB,GAAG,MAAMV,oBAAoB,CAACW,cAAc,CAClEF,gBAAgB,CAACG,MAAM,CAACC,GAAG,EAC3BP,OACJ,CAAC;IACDF,SAAS,CAACU,iBAAiB,CAACJ,oBAAoB,CAAC;EACrD;AACJ,CAAC","ignoreList":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionSrcResolver } from "../../utils/index.js";
|
|
2
2
|
import { AdminAfterBuild as AdminAfterBuildExt, AdminAfterDeploy as AdminAfterDeployExt, AdminBeforeBuild as AdminBeforeBuildExt, AdminBeforeDeploy as AdminBeforeDeployExt, AdminBeforeWatch as AdminBeforeWatchExt, AfterBuild as AfterBuildExt, BeforeWatch as BeforeWatchExt, ApiAfterBuild as ApiAfterBuildExt, ApiAfterDeploy as ApiAfterDeployExt, ApiBeforeBuild as ApiBeforeBuildExt, ApiBeforeDeploy as ApiBeforeDeployExt, ApiBeforeWatch as ApiBeforeWatchExt, BeforeBuild as BeforeBuildExt, BeforeDeploy as BeforeDeployExt, AfterDeploy as AfterDeployExt, CoreAfterBuild as CoreAfterBuildExt, CoreAfterDeploy as CoreAfterDeployExt, CoreBeforeBuild as CoreBeforeBuildExt, CoreBeforeDeploy as CoreBeforeDeployExt, CoreBeforeWatch as CoreBeforeWatchExt } from "../../extensions/hooks/index.js";
|
|
3
3
|
export const registerHooks = async (container, projectExtensions, project) => {
|
|
4
4
|
const hooksExtensions = [...projectExtensions.extensionsByType(AdminAfterBuildExt), ...projectExtensions.extensionsByType(BeforeBuildExt), ...projectExtensions.extensionsByType(BeforeWatchExt), ...projectExtensions.extensionsByType(AfterBuildExt), ...projectExtensions.extensionsByType(BeforeDeployExt), ...projectExtensions.extensionsByType(AfterDeployExt), ...projectExtensions.extensionsByType(AdminBeforeBuildExt), ...projectExtensions.extensionsByType(AdminBeforeDeployExt), ...projectExtensions.extensionsByType(AdminBeforeWatchExt), ...projectExtensions.extensionsByType(AdminAfterBuildExt), ...projectExtensions.extensionsByType(AdminAfterDeployExt), ...projectExtensions.extensionsByType(ApiBeforeBuildExt), ...projectExtensions.extensionsByType(ApiBeforeDeployExt), ...projectExtensions.extensionsByType(ApiBeforeWatchExt), ...projectExtensions.extensionsByType(ApiAfterBuildExt), ...projectExtensions.extensionsByType(ApiAfterDeployExt), ...projectExtensions.extensionsByType(CoreBeforeBuildExt), ...projectExtensions.extensionsByType(CoreBeforeDeployExt), ...projectExtensions.extensionsByType(CoreBeforeWatchExt), ...projectExtensions.extensionsByType(CoreAfterBuildExt), ...projectExtensions.extensionsByType(CoreAfterDeployExt)];
|
|
5
5
|
for (const hookExtension of hooksExtensions) {
|
|
6
|
-
const hookImpl = await
|
|
6
|
+
const hookImpl = await ExtensionSrcResolver.importFromPath(hookExtension.params.src, project);
|
|
7
7
|
container.register(hookImpl).inSingletonScope();
|
|
8
8
|
}
|
|
9
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["ExtensionSrcResolver","AdminAfterBuild","AdminAfterBuildExt","AdminAfterDeploy","AdminAfterDeployExt","AdminBeforeBuild","AdminBeforeBuildExt","AdminBeforeDeploy","AdminBeforeDeployExt","AdminBeforeWatch","AdminBeforeWatchExt","AfterBuild","AfterBuildExt","BeforeWatch","BeforeWatchExt","ApiAfterBuild","ApiAfterBuildExt","ApiAfterDeploy","ApiAfterDeployExt","ApiBeforeBuild","ApiBeforeBuildExt","ApiBeforeDeploy","ApiBeforeDeployExt","ApiBeforeWatch","ApiBeforeWatchExt","BeforeBuild","BeforeBuildExt","BeforeDeploy","BeforeDeployExt","AfterDeploy","AfterDeployExt","CoreAfterBuild","CoreAfterBuildExt","CoreAfterDeploy","CoreAfterDeployExt","CoreBeforeBuild","CoreBeforeBuildExt","CoreBeforeDeploy","CoreBeforeDeployExt","CoreBeforeWatch","CoreBeforeWatchExt","registerHooks","container","projectExtensions","project","hooksExtensions","extensionsByType","hookExtension","hookImpl","importFromPath","params","src","register","inSingletonScope"],"sources":["registerHooks.ts"],"sourcesContent":["import { type IProjectModel } from \"~/abstractions/models/index.js\";\nimport { type IProjectConfigModel } from \"~/abstractions/models/index.js\";\nimport { Container } from \"@webiny/di\";\nimport { ExtensionSrcResolver } from \"~/utils/index.js\";\nimport {\n AdminAfterBuild as AdminAfterBuildExt,\n AdminAfterDeploy as AdminAfterDeployExt,\n AdminBeforeBuild as AdminBeforeBuildExt,\n AdminBeforeDeploy as AdminBeforeDeployExt,\n AdminBeforeWatch as AdminBeforeWatchExt,\n AfterBuild as AfterBuildExt,\n BeforeWatch as BeforeWatchExt,\n ApiAfterBuild as ApiAfterBuildExt,\n ApiAfterDeploy as ApiAfterDeployExt,\n ApiBeforeBuild as ApiBeforeBuildExt,\n ApiBeforeDeploy as ApiBeforeDeployExt,\n ApiBeforeWatch as ApiBeforeWatchExt,\n BeforeBuild as BeforeBuildExt,\n BeforeDeploy as BeforeDeployExt,\n AfterDeploy as AfterDeployExt,\n CoreAfterBuild as CoreAfterBuildExt,\n CoreAfterDeploy as CoreAfterDeployExt,\n CoreBeforeBuild as CoreBeforeBuildExt,\n CoreBeforeDeploy as CoreBeforeDeployExt,\n CoreBeforeWatch as CoreBeforeWatchExt\n} from \"~/extensions/hooks/index.js\";\n\nexport const registerHooks = async (\n container: Container,\n projectExtensions: IProjectConfigModel,\n project: IProjectModel\n) => {\n const hooksExtensions = [\n ...projectExtensions.extensionsByType(AdminAfterBuildExt),\n ...projectExtensions.extensionsByType(BeforeBuildExt),\n ...projectExtensions.extensionsByType(BeforeWatchExt),\n ...projectExtensions.extensionsByType(AfterBuildExt),\n ...projectExtensions.extensionsByType(BeforeDeployExt),\n ...projectExtensions.extensionsByType(AfterDeployExt),\n ...projectExtensions.extensionsByType(AdminBeforeBuildExt),\n ...projectExtensions.extensionsByType(AdminBeforeDeployExt),\n ...projectExtensions.extensionsByType(AdminBeforeWatchExt),\n ...projectExtensions.extensionsByType(AdminAfterBuildExt),\n ...projectExtensions.extensionsByType(AdminAfterDeployExt),\n ...projectExtensions.extensionsByType(ApiBeforeBuildExt),\n ...projectExtensions.extensionsByType(ApiBeforeDeployExt),\n ...projectExtensions.extensionsByType(ApiBeforeWatchExt),\n ...projectExtensions.extensionsByType(ApiAfterBuildExt),\n ...projectExtensions.extensionsByType(ApiAfterDeployExt),\n ...projectExtensions.extensionsByType(CoreBeforeBuildExt),\n ...projectExtensions.extensionsByType(CoreBeforeDeployExt),\n ...projectExtensions.extensionsByType(CoreBeforeWatchExt),\n ...projectExtensions.extensionsByType(CoreAfterBuildExt),\n ...projectExtensions.extensionsByType(CoreAfterDeployExt)\n ];\n\n for (const hookExtension of hooksExtensions) {\n const hookImpl = await ExtensionSrcResolver.importFromPath(\n hookExtension.params.src,\n project\n );\n container.register(hookImpl).inSingletonScope();\n }\n};\n"],"mappings":"AAGA,SAASA,oBAAoB;AAC7B,SACIC,eAAe,IAAIC,kBAAkB,EACrCC,gBAAgB,IAAIC,mBAAmB,EACvCC,gBAAgB,IAAIC,mBAAmB,EACvCC,iBAAiB,IAAIC,oBAAoB,EACzCC,gBAAgB,IAAIC,mBAAmB,EACvCC,UAAU,IAAIC,aAAa,EAC3BC,WAAW,IAAIC,cAAc,EAC7BC,aAAa,IAAIC,gBAAgB,EACjCC,cAAc,IAAIC,iBAAiB,EACnCC,cAAc,IAAIC,iBAAiB,EACnCC,eAAe,IAAIC,kBAAkB,EACrCC,cAAc,IAAIC,iBAAiB,EACnCC,WAAW,IAAIC,cAAc,EAC7BC,YAAY,IAAIC,eAAe,EAC/BC,WAAW,IAAIC,cAAc,EAC7BC,cAAc,IAAIC,iBAAiB,EACnCC,eAAe,IAAIC,kBAAkB,EACrCC,eAAe,IAAIC,kBAAkB,EACrCC,gBAAgB,IAAIC,mBAAmB,EACvCC,eAAe,IAAIC,kBAAkB;AAGzC,OAAO,MAAMC,aAAa,GAAG,MAAAA,CACzBC,SAAoB,EACpBC,iBAAsC,EACtCC,OAAsB,KACrB;EACD,MAAMC,eAAe,GAAG,CACpB,GAAGF,iBAAiB,CAACG,gBAAgB,CAAC5C,kBAAkB,CAAC,EACzD,GAAGyC,iBAAiB,CAACG,gBAAgB,CAACpB,cAAc,CAAC,EACrD,GAAGiB,iBAAiB,CAACG,gBAAgB,CAAChC,cAAc,CAAC,EACrD,GAAG6B,iBAAiB,CAACG,gBAAgB,CAAClC,aAAa,CAAC,EACpD,GAAG+B,iBAAiB,CAACG,gBAAgB,CAAClB,eAAe,CAAC,EACtD,GAAGe,iBAAiB,CAACG,gBAAgB,CAAChB,cAAc,CAAC,EACrD,GAAGa,iBAAiB,CAACG,gBAAgB,CAACxC,mBAAmB,CAAC,EAC1D,GAAGqC,iBAAiB,CAACG,gBAAgB,CAACtC,oBAAoB,CAAC,EAC3D,GAAGmC,iBAAiB,CAACG,gBAAgB,CAACpC,mBAAmB,CAAC,EAC1D,GAAGiC,iBAAiB,CAACG,gBAAgB,CAAC5C,kBAAkB,CAAC,EACzD,GAAGyC,iBAAiB,CAACG,gBAAgB,CAAC1C,mBAAmB,CAAC,EAC1D,GAAGuC,iBAAiB,CAACG,gBAAgB,CAAC1B,iBAAiB,CAAC,EACxD,GAAGuB,iBAAiB,CAACG,gBAAgB,CAACxB,kBAAkB,CAAC,EACzD,GAAGqB,iBAAiB,CAACG,gBAAgB,CAACtB,iBAAiB,CAAC,EACxD,GAAGmB,iBAAiB,CAACG,gBAAgB,CAAC9B,gBAAgB,CAAC,EACvD,GAAG2B,iBAAiB,CAACG,gBAAgB,CAAC5B,iBAAiB,CAAC,EACxD,GAAGyB,iBAAiB,CAACG,gBAAgB,CAACV,kBAAkB,CAAC,EACzD,GAAGO,iBAAiB,CAACG,gBAAgB,CAACR,mBAAmB,CAAC,EAC1D,GAAGK,iBAAiB,CAACG,gBAAgB,CAACN,kBAAkB,CAAC,EACzD,GAAGG,iBAAiB,CAACG,gBAAgB,CAACd,iBAAiB,CAAC,EACxD,GAAGW,iBAAiB,CAACG,gBAAgB,CAACZ,kBAAkB,CAAC,CAC5D;EAED,KAAK,MAAMa,aAAa,IAAIF,eAAe,EAAE;IACzC,MAAMG,QAAQ,GAAG,MAAMhD,oBAAoB,CAACiD,cAAc,CACtDF,aAAa,CAACG,MAAM,CAACC,GAAG,EACxBP,OACJ,CAAC;IACDF,SAAS,CAACU,QAAQ,CAACJ,QAAQ,CAAC,CAACK,gBAAgB,CAAC,CAAC;EACnD;AACJ,CAAC","ignoreList":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionSrcResolver } from "../../utils/index.js";
|
|
2
2
|
import { ProjectImplementation as ProjectImplementationExt } from "../../extensions/ProjectImplementation.js";
|
|
3
3
|
export const registerImplementations = async (container, projectExtensions, project) => {
|
|
4
4
|
const projectImplementations = [...projectExtensions.extensionsByType(ProjectImplementationExt)];
|
|
5
5
|
for (const projectImplementation of projectImplementations) {
|
|
6
|
-
const projectImplementationImpl = await
|
|
6
|
+
const projectImplementationImpl = await ExtensionSrcResolver.importFromPath(projectImplementation.params.src, project);
|
|
7
7
|
const binding = container.register(projectImplementationImpl);
|
|
8
8
|
|
|
9
9
|
// Apply singleton scope if specified (defaults to true)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["ExtensionSrcResolver","ProjectImplementation","ProjectImplementationExt","registerImplementations","container","projectExtensions","project","projectImplementations","extensionsByType","projectImplementation","projectImplementationImpl","importFromPath","params","src","binding","register","singleton","inSingletonScope"],"sources":["registerImplementations.ts"],"sourcesContent":["import { type IProjectModel } from \"~/abstractions/models/index.js\";\nimport { type IProjectConfigModel } from \"~/abstractions/models/index.js\";\nimport { Container } from \"@webiny/di\";\nimport { ExtensionSrcResolver } from \"~/utils/index.js\";\nimport { ProjectImplementation as ProjectImplementationExt } from \"~/extensions/ProjectImplementation.js\";\n\nexport const registerImplementations = async (\n container: Container,\n projectExtensions: IProjectConfigModel,\n project: IProjectModel\n) => {\n const projectImplementations = [\n ...projectExtensions.extensionsByType(ProjectImplementationExt)\n ];\n\n for (const projectImplementation of projectImplementations) {\n const projectImplementationImpl = await ExtensionSrcResolver.importFromPath(\n projectImplementation.params.src,\n project\n );\n const binding = container.register(projectImplementationImpl);\n\n // Apply singleton scope if specified (defaults to true)\n if (projectImplementation.params.singleton) {\n binding.inSingletonScope();\n }\n }\n};\n"],"mappings":"AAGA,SAASA,oBAAoB;AAC7B,SAASC,qBAAqB,IAAIC,wBAAwB;AAE1D,OAAO,MAAMC,uBAAuB,GAAG,MAAAA,CACnCC,SAAoB,EACpBC,iBAAsC,EACtCC,OAAsB,KACrB;EACD,MAAMC,sBAAsB,GAAG,CAC3B,GAAGF,iBAAiB,CAACG,gBAAgB,CAACN,wBAAwB,CAAC,CAClE;EAED,KAAK,MAAMO,qBAAqB,IAAIF,sBAAsB,EAAE;IACxD,MAAMG,yBAAyB,GAAG,MAAMV,oBAAoB,CAACW,cAAc,CACvEF,qBAAqB,CAACG,MAAM,CAACC,GAAG,EAChCP,OACJ,CAAC;IACD,MAAMQ,OAAO,GAAGV,SAAS,CAACW,QAAQ,CAACL,yBAAyB,CAAC;;IAE7D;IACA,IAAID,qBAAqB,CAACG,MAAM,CAACI,SAAS,EAAE;MACxCF,OAAO,CAACG,gBAAgB,CAAC,CAAC;IAC9B;EACJ;AACJ,CAAC","ignoreList":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionSrcResolver } from "../../utils/index.js";
|
|
2
2
|
import { CorePulumi as CorePulumiExt, ApiPulumi as ApiPulumiExt, AdminPulumi as AdminPulumiExt } from "../../extensions/pulumi/index.js";
|
|
3
3
|
export const registerPulumiExtensions = async (container, projectExtensions, project) => {
|
|
4
4
|
const pulumiExtensions = [...projectExtensions.extensionsByType(CorePulumiExt), ...projectExtensions.extensionsByType(ApiPulumiExt), ...projectExtensions.extensionsByType(AdminPulumiExt)];
|
|
5
5
|
for (const pulumiExtension of pulumiExtensions) {
|
|
6
|
-
const pulumiImpl = await
|
|
6
|
+
const pulumiImpl = await ExtensionSrcResolver.importFromPath(pulumiExtension.params.src, project);
|
|
7
7
|
container.register(pulumiImpl).inSingletonScope();
|
|
8
8
|
}
|
|
9
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["ExtensionSrcResolver","CorePulumi","CorePulumiExt","ApiPulumi","ApiPulumiExt","AdminPulumi","AdminPulumiExt","registerPulumiExtensions","container","projectExtensions","project","pulumiExtensions","extensionsByType","pulumiExtension","pulumiImpl","importFromPath","params","src","register","inSingletonScope"],"sources":["registerPulumiExtensions.ts"],"sourcesContent":["import { type IProjectModel } from \"~/abstractions/models/index.js\";\nimport { type IProjectConfigModel } from \"~/abstractions/models/index.js\";\nimport { Container } from \"@webiny/di\";\nimport { ExtensionSrcResolver } from \"~/utils/index.js\";\nimport {\n CorePulumi as CorePulumiExt,\n ApiPulumi as ApiPulumiExt,\n AdminPulumi as AdminPulumiExt\n} from \"~/extensions/pulumi/index.js\";\n\nexport const registerPulumiExtensions = async (\n container: Container,\n projectExtensions: IProjectConfigModel,\n project: IProjectModel\n) => {\n const pulumiExtensions = [\n ...projectExtensions.extensionsByType(CorePulumiExt),\n ...projectExtensions.extensionsByType(ApiPulumiExt),\n ...projectExtensions.extensionsByType(AdminPulumiExt)\n ];\n\n for (const pulumiExtension of pulumiExtensions) {\n const pulumiImpl = await ExtensionSrcResolver.importFromPath(\n pulumiExtension.params.src,\n project\n );\n container.register(pulumiImpl).inSingletonScope();\n }\n};\n"],"mappings":"AAGA,SAASA,oBAAoB;AAC7B,SACIC,UAAU,IAAIC,aAAa,EAC3BC,SAAS,IAAIC,YAAY,EACzBC,WAAW,IAAIC,cAAc;AAGjC,OAAO,MAAMC,wBAAwB,GAAG,MAAAA,CACpCC,SAAoB,EACpBC,iBAAsC,EACtCC,OAAsB,KACrB;EACD,MAAMC,gBAAgB,GAAG,CACrB,GAAGF,iBAAiB,CAACG,gBAAgB,CAACV,aAAa,CAAC,EACpD,GAAGO,iBAAiB,CAACG,gBAAgB,CAACR,YAAY,CAAC,EACnD,GAAGK,iBAAiB,CAACG,gBAAgB,CAACN,cAAc,CAAC,CACxD;EAED,KAAK,MAAMO,eAAe,IAAIF,gBAAgB,EAAE;IAC5C,MAAMG,UAAU,GAAG,MAAMd,oBAAoB,CAACe,cAAc,CACxDF,eAAe,CAACG,MAAM,CAACC,GAAG,EAC1BP,OACJ,CAAC;IACDF,SAAS,CAACU,QAAQ,CAACJ,UAAU,CAAC,CAACK,gBAAgB,CAAC,CAAC;EACrD;AACJ,CAAC","ignoreList":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GetProjectService, GetProjectVersionService, InstallExtensionService } from "../../abstractions/index.js";
|
|
2
2
|
declare class DefaultInstallExtensionService implements InstallExtensionService.Interface {
|
|
3
3
|
private getProjectVersion;
|
|
4
4
|
private getProject;
|
|
@@ -2,9 +2,9 @@ import os from "os";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import fsAsync from "fs/promises";
|
|
5
|
-
import
|
|
5
|
+
import { loadJsonFileSync } from "load-json-file";
|
|
6
6
|
import { createImplementation } from "@webiny/di";
|
|
7
|
-
import {
|
|
7
|
+
import { GetProjectService, GetProjectVersionService, InstallExtensionService } from "../../abstractions/index.js";
|
|
8
8
|
import { downloadFolderFromS3 } from "./downloadFolderFromS3.js";
|
|
9
9
|
import { mergePackageJson } from "./mergePackageJson.js";
|
|
10
10
|
import { updateWebinyConfig } from "./updateWebinyConfig.js";
|
|
@@ -85,7 +85,7 @@ class DefaultInstallExtensionService {
|
|
|
85
85
|
|
|
86
86
|
// Read and parse extension.json.
|
|
87
87
|
const extensionJsonExists = fs.existsSync(extensionJsonPath);
|
|
88
|
-
const extensionJson = extensionJsonExists ?
|
|
88
|
+
const extensionJson = extensionJsonExists ? loadJsonFileSync(extensionJsonPath) : {
|
|
89
89
|
name: "unknown",
|
|
90
90
|
type: "admin"
|
|
91
91
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["os","path","fs","fsAsync","loadJsonFile","createImplementation","InstallExtensionService","GetProjectVersionService","GetProjectService","downloadFolderFromS3","mergePackageJson","updateWebinyConfig","EXTENSIONS_ROOT_FOLDER","S3_BUCKET_NAME","S3_BUCKET_REGION","FOLDER_NAME_IS_VERSION_REGEX","WEBINY_DEV_VERSION","getVersionFromVersionFolders","versionFoldersList","currentWebinyVersion","availableVersions","filter","v","match","map","replace","sort","versionToUse","startsWith","length","availableVersion","DefaultInstallExtensionService","constructor","getProjectVersion","getProject","execute","source","project","projectRoot","paths","rootFolder","toString","randomId","String","Date","now","downloadFolderPath","join","tmpdir","isLocalPath","resolvedPath","isAbsolute","resolve","cp","recursive","bucketName","bucketRegion","bucketFolderKey","extensionsFolderToCopyPath","extensionJsonPath","extensionsFolderExistsInRoot","existsSync","versionedExtension","versionFolders","readdir","subExtensionJsonPath","extensionJsonExists","extensionJson","name","type","targetExtensionsFolder","mkdirSync","extensionsFolderNames","extensionPaths","packageJson","Object","keys","extensionPackageJson","webinyConfigTsx","nextSteps","messages","additionalNotes","extensionName","installExtensionService","abstraction","implementation","dependencies"],"sources":["InstallExtensionService.ts"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport fsAsync from \"fs/promises\";\nimport loadJsonFile from \"load-json-file\";\nimport { createImplementation } from \"@webiny/di\";\nimport {\n InstallExtensionService,\n GetProjectVersionService,\n GetProjectService\n} from \"~/abstractions/index.js\";\nimport { downloadFolderFromS3 } from \"./downloadFolderFromS3.js\";\nimport { mergePackageJson } from \"./mergePackageJson.js\";\nimport { updateWebinyConfig } from \"./updateWebinyConfig.js\";\nimport type { ExtensionJson } from \"./types.js\";\n\nconst EXTENSIONS_ROOT_FOLDER = \"extensions\";\nconst S3_BUCKET_NAME = \"webiny-examples\";\nconst S3_BUCKET_REGION = \"us-east-1\";\nconst FOLDER_NAME_IS_VERSION_REGEX = /^\\d+\\.\\d+\\.x$/;\nconst WEBINY_DEV_VERSION = \"0.0.0\";\n\nconst getVersionFromVersionFolders = async (\n versionFoldersList: string[],\n currentWebinyVersion: string\n) => {\n const availableVersions = versionFoldersList\n .filter(v => v.match(FOLDER_NAME_IS_VERSION_REGEX))\n .map(v => v.replace(/\\.x$/, \".0\"))\n .sort();\n\n let versionToUse = \"\";\n\n // When developing Webiny, we want to use the latest version.\n if (currentWebinyVersion.startsWith(WEBINY_DEV_VERSION)) {\n versionToUse = availableVersions[availableVersions.length - 1];\n } else {\n for (const availableVersion of availableVersions) {\n if (currentWebinyVersion >= availableVersion) {\n versionToUse = availableVersion;\n } else {\n break;\n }\n }\n }\n\n return versionToUse.replace(/\\.0$/, \".x\");\n};\n\nclass DefaultInstallExtensionService implements InstallExtensionService.Interface {\n constructor(\n private getProjectVersion: GetProjectVersionService.Interface,\n private getProject: GetProjectService.Interface\n ) {}\n\n async execute(source: string): Promise<InstallExtensionService.Result> {\n const currentWebinyVersion = this.getProjectVersion.execute();\n const project = this.getProject.execute();\n const projectRoot = project.paths.rootFolder.toString();\n\n const randomId = String(Date.now());\n const downloadFolderPath = path.join(os.tmpdir(), `wby-ext-${randomId}`);\n\n // Check if source is a local path\n const isLocalPath =\n source.startsWith(\"../\") || source.startsWith(\"./\") || source.startsWith(\"/\");\n\n if (isLocalPath) {\n // Resolve the local path relative to the project root\n const resolvedPath = path.isAbsolute(source)\n ? source\n : path.resolve(projectRoot, source);\n\n // Copy the local directory to the temporary download folder\n await fsAsync.cp(resolvedPath, downloadFolderPath, {\n recursive: true\n });\n } else {\n // Download from S3\n await downloadFolderFromS3({\n bucketName: S3_BUCKET_NAME,\n bucketRegion: S3_BUCKET_REGION,\n bucketFolderKey: source,\n downloadFolderPath\n });\n }\n\n let extensionsFolderToCopyPath = path.join(downloadFolderPath, \"extensions\");\n let extensionJsonPath = path.join(downloadFolderPath, \"extension.json\");\n\n // If we have `extensions` folder in the root of the downloaded extension,\n // it means the extension is not versioned, and we can just copy it.\n const extensionsFolderExistsInRoot = fs.existsSync(extensionsFolderToCopyPath);\n const versionedExtension = !extensionsFolderExistsInRoot;\n\n if (versionedExtension) {\n // If we have `x.x.x` folders in the root of the downloaded\n // extension, we need to find the right version to use.\n\n // This can be `5.40.x`, `6.0.x`, etc.\n const versionFolders = await fsAsync.readdir(downloadFolderPath);\n\n const versionToUse = await getVersionFromVersionFolders(\n versionFolders,\n currentWebinyVersion\n );\n\n extensionsFolderToCopyPath = path.join(downloadFolderPath, versionToUse, \"extensions\");\n const subExtensionJsonPath = path.join(\n downloadFolderPath,\n versionToUse,\n \"extension.json\"\n );\n if (fs.existsSync(subExtensionJsonPath)) {\n extensionJsonPath = subExtensionJsonPath;\n }\n }\n\n // Read and parse extension.json.\n const extensionJsonExists = fs.existsSync(extensionJsonPath);\n const extensionJson: ExtensionJson = extensionJsonExists\n ? await loadJsonFile(extensionJsonPath)\n : { name: \"unknown\", type: \"admin\" };\n\n // Ensure the extensions root folder exists.\n const targetExtensionsFolder = path.join(projectRoot, EXTENSIONS_ROOT_FOLDER);\n if (!fs.existsSync(targetExtensionsFolder)) {\n fs.mkdirSync(targetExtensionsFolder, { recursive: true });\n }\n\n // Copy the extensions folder contents.\n await fsAsync.cp(extensionsFolderToCopyPath, targetExtensionsFolder, {\n recursive: true\n });\n\n // Get the list of extensions that were copied.\n const extensionsFolderNames = await fsAsync.readdir(extensionsFolderToCopyPath);\n const extensionPaths = extensionsFolderNames.map(name =>\n path.join(EXTENSIONS_ROOT_FOLDER, name)\n );\n\n // Merge package.json if provided.\n if (extensionJson.packageJson && Object.keys(extensionJson.packageJson).length > 0) {\n await mergePackageJson({\n projectRoot,\n extensionPackageJson: extensionJson.packageJson\n });\n }\n\n // Update webiny.config.tsx if provided.\n if (extensionJson.webinyConfigTsx) {\n await updateWebinyConfig({\n projectRoot,\n webinyConfigTsx: extensionJson.webinyConfigTsx\n });\n }\n\n // Extract next steps and additional notes.\n const nextSteps = extensionJson.nextSteps?.messages || [];\n const additionalNotes = extensionJson.additionalNotes?.messages || [];\n\n return {\n extensionName: extensionJson.name,\n extensionPaths,\n nextSteps,\n additionalNotes\n };\n }\n}\n\nexport const installExtensionService = createImplementation({\n abstraction: InstallExtensionService,\n implementation: DefaultInstallExtensionService,\n dependencies: [GetProjectVersionService, GetProjectService]\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["os","path","fs","fsAsync","loadJsonFileSync","createImplementation","GetProjectService","GetProjectVersionService","InstallExtensionService","downloadFolderFromS3","mergePackageJson","updateWebinyConfig","EXTENSIONS_ROOT_FOLDER","S3_BUCKET_NAME","S3_BUCKET_REGION","FOLDER_NAME_IS_VERSION_REGEX","WEBINY_DEV_VERSION","getVersionFromVersionFolders","versionFoldersList","currentWebinyVersion","availableVersions","filter","v","match","map","replace","sort","versionToUse","startsWith","length","availableVersion","DefaultInstallExtensionService","constructor","getProjectVersion","getProject","execute","source","project","projectRoot","paths","rootFolder","toString","randomId","String","Date","now","downloadFolderPath","join","tmpdir","isLocalPath","resolvedPath","isAbsolute","resolve","cp","recursive","bucketName","bucketRegion","bucketFolderKey","extensionsFolderToCopyPath","extensionJsonPath","extensionsFolderExistsInRoot","existsSync","versionedExtension","versionFolders","readdir","subExtensionJsonPath","extensionJsonExists","extensionJson","name","type","targetExtensionsFolder","mkdirSync","extensionsFolderNames","extensionPaths","packageJson","Object","keys","extensionPackageJson","webinyConfigTsx","nextSteps","messages","additionalNotes","extensionName","installExtensionService","abstraction","implementation","dependencies"],"sources":["InstallExtensionService.ts"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport fsAsync from \"fs/promises\";\nimport { loadJsonFileSync } from \"load-json-file\";\nimport { createImplementation } from \"@webiny/di\";\nimport {\n GetProjectService,\n GetProjectVersionService,\n InstallExtensionService\n} from \"~/abstractions/index.js\";\nimport { downloadFolderFromS3 } from \"./downloadFolderFromS3.js\";\nimport { mergePackageJson } from \"./mergePackageJson.js\";\nimport { updateWebinyConfig } from \"./updateWebinyConfig.js\";\nimport type { ExtensionJson } from \"./types.js\";\n\nconst EXTENSIONS_ROOT_FOLDER = \"extensions\";\nconst S3_BUCKET_NAME = \"webiny-examples\";\nconst S3_BUCKET_REGION = \"us-east-1\";\nconst FOLDER_NAME_IS_VERSION_REGEX = /^\\d+\\.\\d+\\.x$/;\nconst WEBINY_DEV_VERSION = \"0.0.0\";\n\nconst getVersionFromVersionFolders = async (\n versionFoldersList: string[],\n currentWebinyVersion: string\n) => {\n const availableVersions = versionFoldersList\n .filter(v => v.match(FOLDER_NAME_IS_VERSION_REGEX))\n .map(v => v.replace(/\\.x$/, \".0\"))\n .sort();\n\n let versionToUse = \"\";\n\n // When developing Webiny, we want to use the latest version.\n if (currentWebinyVersion.startsWith(WEBINY_DEV_VERSION)) {\n versionToUse = availableVersions[availableVersions.length - 1];\n } else {\n for (const availableVersion of availableVersions) {\n if (currentWebinyVersion >= availableVersion) {\n versionToUse = availableVersion;\n } else {\n break;\n }\n }\n }\n\n return versionToUse.replace(/\\.0$/, \".x\");\n};\n\nclass DefaultInstallExtensionService implements InstallExtensionService.Interface {\n constructor(\n private getProjectVersion: GetProjectVersionService.Interface,\n private getProject: GetProjectService.Interface\n ) {}\n\n async execute(source: string): Promise<InstallExtensionService.Result> {\n const currentWebinyVersion = this.getProjectVersion.execute();\n const project = this.getProject.execute();\n const projectRoot = project.paths.rootFolder.toString();\n\n const randomId = String(Date.now());\n const downloadFolderPath = path.join(os.tmpdir(), `wby-ext-${randomId}`);\n\n // Check if source is a local path\n const isLocalPath =\n source.startsWith(\"../\") || source.startsWith(\"./\") || source.startsWith(\"/\");\n\n if (isLocalPath) {\n // Resolve the local path relative to the project root\n const resolvedPath = path.isAbsolute(source)\n ? source\n : path.resolve(projectRoot, source);\n\n // Copy the local directory to the temporary download folder\n await fsAsync.cp(resolvedPath, downloadFolderPath, {\n recursive: true\n });\n } else {\n // Download from S3\n await downloadFolderFromS3({\n bucketName: S3_BUCKET_NAME,\n bucketRegion: S3_BUCKET_REGION,\n bucketFolderKey: source,\n downloadFolderPath\n });\n }\n\n let extensionsFolderToCopyPath = path.join(downloadFolderPath, \"extensions\");\n let extensionJsonPath = path.join(downloadFolderPath, \"extension.json\");\n\n // If we have `extensions` folder in the root of the downloaded extension,\n // it means the extension is not versioned, and we can just copy it.\n const extensionsFolderExistsInRoot = fs.existsSync(extensionsFolderToCopyPath);\n const versionedExtension = !extensionsFolderExistsInRoot;\n\n if (versionedExtension) {\n // If we have `x.x.x` folders in the root of the downloaded\n // extension, we need to find the right version to use.\n\n // This can be `5.40.x`, `6.0.x`, etc.\n const versionFolders = await fsAsync.readdir(downloadFolderPath);\n\n const versionToUse = await getVersionFromVersionFolders(\n versionFolders,\n currentWebinyVersion\n );\n\n extensionsFolderToCopyPath = path.join(downloadFolderPath, versionToUse, \"extensions\");\n const subExtensionJsonPath = path.join(\n downloadFolderPath,\n versionToUse,\n \"extension.json\"\n );\n if (fs.existsSync(subExtensionJsonPath)) {\n extensionJsonPath = subExtensionJsonPath;\n }\n }\n\n // Read and parse extension.json.\n const extensionJsonExists = fs.existsSync(extensionJsonPath);\n const extensionJson: ExtensionJson = extensionJsonExists\n ? loadJsonFileSync(extensionJsonPath)\n : { name: \"unknown\", type: \"admin\" };\n\n // Ensure the extensions root folder exists.\n const targetExtensionsFolder = path.join(projectRoot, EXTENSIONS_ROOT_FOLDER);\n if (!fs.existsSync(targetExtensionsFolder)) {\n fs.mkdirSync(targetExtensionsFolder, { recursive: true });\n }\n\n // Copy the extensions folder contents.\n await fsAsync.cp(extensionsFolderToCopyPath, targetExtensionsFolder, {\n recursive: true\n });\n\n // Get the list of extensions that were copied.\n const extensionsFolderNames = await fsAsync.readdir(extensionsFolderToCopyPath);\n const extensionPaths = extensionsFolderNames.map(name =>\n path.join(EXTENSIONS_ROOT_FOLDER, name)\n );\n\n // Merge package.json if provided.\n if (extensionJson.packageJson && Object.keys(extensionJson.packageJson).length > 0) {\n await mergePackageJson({\n projectRoot,\n extensionPackageJson: extensionJson.packageJson\n });\n }\n\n // Update webiny.config.tsx if provided.\n if (extensionJson.webinyConfigTsx) {\n await updateWebinyConfig({\n projectRoot,\n webinyConfigTsx: extensionJson.webinyConfigTsx\n });\n }\n\n // Extract next steps and additional notes.\n const nextSteps = extensionJson.nextSteps?.messages || [];\n const additionalNotes = extensionJson.additionalNotes?.messages || [];\n\n return {\n extensionName: extensionJson.name,\n extensionPaths,\n nextSteps,\n additionalNotes\n };\n }\n}\n\nexport const installExtensionService = createImplementation({\n abstraction: InstallExtensionService,\n implementation: DefaultInstallExtensionService,\n dependencies: [GetProjectVersionService, GetProjectService]\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { loadJsonFileSync } from "load-json-file";
|
|
2
|
+
import { writeJsonFileSync } from "write-json-file";
|
|
3
3
|
import deepmerge from "deepmerge";
|
|
4
4
|
/**
|
|
5
5
|
* Merge extension package.json properties into the project's root package.json.
|
|
@@ -12,7 +12,7 @@ export const mergePackageJson = async params => {
|
|
|
12
12
|
const packageJsonPath = `${projectRoot}/package.json`;
|
|
13
13
|
|
|
14
14
|
// Load the current package.json
|
|
15
|
-
const currentPackageJson = await
|
|
15
|
+
const currentPackageJson = await loadJsonFileSync(packageJsonPath);
|
|
16
16
|
|
|
17
17
|
// Merge the extension's package.json into the current one
|
|
18
18
|
// Use deepmerge to combine arrays and objects properly
|
|
@@ -25,7 +25,7 @@ export const mergePackageJson = async params => {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
// Write the merged package.json back
|
|
28
|
-
|
|
28
|
+
return writeJsonFileSync(packageJsonPath, mergedPackageJson);
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
//# sourceMappingURL=mergePackageJson.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["loadJsonFileSync","writeJsonFileSync","deepmerge","mergePackageJson","params","projectRoot","extensionPackageJson","packageJsonPath","currentPackageJson","mergedPackageJson","arrayMerge","target","source","combined","Array","from","Set"],"sources":["mergePackageJson.ts"],"sourcesContent":["import { loadJsonFileSync } from \"load-json-file\";\nimport { writeJsonFileSync } from \"write-json-file\";\nimport deepmerge from \"deepmerge\";\n\ninterface MergePackageJsonParams {\n projectRoot: string;\n extensionPackageJson: Record<string, any>;\n}\n\n/**\n * Merge extension package.json properties into the project's root package.json.\n */\nexport const mergePackageJson = async (params: MergePackageJsonParams): Promise<void> => {\n const { projectRoot, extensionPackageJson } = params;\n\n const packageJsonPath = `${projectRoot}/package.json`;\n\n // Load the current package.json\n const currentPackageJson = await loadJsonFileSync<Record<string, any>>(packageJsonPath);\n\n // Merge the extension's package.json into the current one\n // Use deepmerge to combine arrays and objects properly\n const mergedPackageJson = deepmerge(currentPackageJson, extensionPackageJson, {\n // For arrays, concatenate and remove duplicates\n arrayMerge: (target, source) => {\n const combined = [...target, ...source];\n return Array.from(new Set(combined));\n }\n });\n\n // Write the merged package.json back\n return writeJsonFileSync(packageJsonPath, mergedPackageJson);\n};\n"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,gBAAgB;AACjD,SAASC,iBAAiB,QAAQ,iBAAiB;AACnD,OAAOC,SAAS,MAAM,WAAW;AAOjC;AACA;AACA;AACA,OAAO,MAAMC,gBAAgB,GAAG,MAAOC,MAA8B,IAAoB;EACrF,MAAM;IAAEC,WAAW;IAAEC;EAAqB,CAAC,GAAGF,MAAM;EAEpD,MAAMG,eAAe,GAAG,GAAGF,WAAW,eAAe;;EAErD;EACA,MAAMG,kBAAkB,GAAG,MAAMR,gBAAgB,CAAsBO,eAAe,CAAC;;EAEvF;EACA;EACA,MAAME,iBAAiB,GAAGP,SAAS,CAACM,kBAAkB,EAAEF,oBAAoB,EAAE;IAC1E;IACAI,UAAU,EAAEA,CAACC,MAAM,EAAEC,MAAM,KAAK;MAC5B,MAAMC,QAAQ,GAAG,CAAC,GAAGF,MAAM,EAAE,GAAGC,MAAM,CAAC;MACvC,OAAOE,KAAK,CAACC,IAAI,CAAC,IAAIC,GAAG,CAACH,QAAQ,CAAC,CAAC;IACxC;EACJ,CAAC,CAAC;;EAEF;EACA,OAAOZ,iBAAiB,CAACM,eAAe,EAAEE,iBAAiB,CAAC;AAChE,CAAC","ignoreList":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createImplementation } from "@webiny/di";
|
|
2
2
|
import { ListAppLambdaFunctionsService, PulumiExportService, LoggerService } from "../../abstractions/index.js";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import minimatch from "minimatch";
|
|
4
|
+
import { minimatch } from "minimatch";
|
|
5
5
|
export class DefaultListAppLambdaFunctionsService {
|
|
6
6
|
constructor(pulumiExportService, loggerService) {
|
|
7
7
|
this.pulumiExportService = pulumiExportService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createImplementation","ListAppLambdaFunctionsService","PulumiExportService","LoggerService","path","minimatch","DefaultListAppLambdaFunctionsService","constructor","pulumiExportService","loggerService","execute","app","params","stackExport","list","meta","count","totalCount","resources","deployment","allFunctionsList","filter","r","type","resource","isAuthorizerFunction","inputs","name","includes","filteredFunctionsList","code","assets","map","fnName","handlerBuildFolderPath","handlerPath","join","whitelist","length","functionNamesToMatch","Array","isArray","fn","some","pattern","listAppLambdaFunctionsService","abstraction","implementation","dependencies"],"sources":["ListAppLambdaFunctionsService.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/di\";\nimport {\n ListAppLambdaFunctionsService,\n PulumiExportService,\n LoggerService\n} from \"~/abstractions/index.js\";\nimport { type AppModel } from \"~/models/index.js\";\nimport path from \"path\";\nimport minimatch from \"minimatch\";\n\ninterface ExpectedStackExport {\n deployment: {\n resources: Array<{\n type: string;\n inputs: {\n name: string;\n code: {\n assets: Record<string, { path: string }>;\n };\n };\n }>;\n };\n}\n\nexport class DefaultListAppLambdaFunctionsService\n implements ListAppLambdaFunctionsService.Interface\n{\n constructor(\n private pulumiExportService: PulumiExportService.Interface,\n private loggerService: LoggerService.Interface\n ) {}\n\n async execute(app: AppModel, params?: ListAppLambdaFunctionsService.Params) {\n const stackExport = await this.pulumiExportService.execute<ExpectedStackExport>(app);\n\n if (!stackExport) {\n // If no stack export is found, return an empty array. This is a valid scenario.\n // For example, watching the Admin app locally, but not deploying it.\n return {\n list: [],\n meta: {\n count: 0,\n totalCount: 0\n }\n };\n }\n\n // If an app is not deployed, resources will not exist.\n const resources = stackExport.deployment?.resources ?? [];\n\n const allFunctionsList = resources\n .filter(r => r.type === \"aws:lambda/function:Function\")\n // We don't need to watch the authorizer function.\n .filter(resource => {\n const isAuthorizerFunction = resource.inputs.name.includes(\n \"watch-command-iot-authorizer\"\n );\n return !isAuthorizerFunction;\n });\n\n let filteredFunctionsList = allFunctionsList\n // First, this filter ensures that Lambda@Edge functions are excluded. Second,\n // it also ensures a function is filtered out if a `pulumi refresh` was called.\n // This is because, when called, the paths in Pulumi state file disappear, and\n // we can't determine the path to the handler. Probably needs revisiting. 🤦♂️\n .filter(resource => {\n return \".\" in resource.inputs.code.assets;\n })\n .map(resource => {\n const fnName = resource.inputs.name;\n const handlerBuildFolderPath = resource.inputs.code.assets[\".\"].path;\n\n const handlerPath = path.join(handlerBuildFolderPath, \"handler.mjs\");\n return {\n name: fnName,\n path: handlerPath\n };\n });\n\n if (params?.whitelist?.length) {\n const functionNamesToMatch = Array.isArray(params.whitelist)\n ? params.whitelist\n : [params.whitelist];\n\n // `functionNamesToWatch` is an array of glob patterns, which denote which functions to watch.\n filteredFunctionsList = filteredFunctionsList.filter(fn => {\n return functionNamesToMatch.some(pattern => {\n if (pattern.includes(\"*\")) {\n return minimatch(fn.name, pattern);\n }\n\n return fn.name.includes(pattern);\n });\n });\n } else {\n // We've hardcoded this filtering here just because of lack of time.\n // With v5, these \"presets\" were located within `webiny.application.ts` files.\n if (app.name === \"api\") {\n filteredFunctionsList = filteredFunctionsList.filter(fn => {\n return fn.name.includes(\"graphql\");\n });\n }\n }\n\n return {\n list: filteredFunctionsList,\n meta: { count: filteredFunctionsList.length, totalCount: allFunctionsList.length }\n };\n }\n}\n\nexport const listAppLambdaFunctionsService = createImplementation({\n abstraction: ListAppLambdaFunctionsService,\n implementation: DefaultListAppLambdaFunctionsService,\n dependencies: [PulumiExportService, LoggerService]\n});\n"],"mappings":"AAAA,SAASA,oBAAoB,QAAQ,YAAY;AACjD,SACIC,6BAA6B,EAC7BC,mBAAmB,EACnBC,aAAa;AAGjB,OAAOC,IAAI,MAAM,MAAM;AACvB,
|
|
1
|
+
{"version":3,"names":["createImplementation","ListAppLambdaFunctionsService","PulumiExportService","LoggerService","path","minimatch","DefaultListAppLambdaFunctionsService","constructor","pulumiExportService","loggerService","execute","app","params","stackExport","list","meta","count","totalCount","resources","deployment","allFunctionsList","filter","r","type","resource","isAuthorizerFunction","inputs","name","includes","filteredFunctionsList","code","assets","map","fnName","handlerBuildFolderPath","handlerPath","join","whitelist","length","functionNamesToMatch","Array","isArray","fn","some","pattern","listAppLambdaFunctionsService","abstraction","implementation","dependencies"],"sources":["ListAppLambdaFunctionsService.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/di\";\nimport {\n ListAppLambdaFunctionsService,\n PulumiExportService,\n LoggerService\n} from \"~/abstractions/index.js\";\nimport { type AppModel } from \"~/models/index.js\";\nimport path from \"path\";\nimport { minimatch } from \"minimatch\";\n\ninterface ExpectedStackExport {\n deployment: {\n resources: Array<{\n type: string;\n inputs: {\n name: string;\n code: {\n assets: Record<string, { path: string }>;\n };\n };\n }>;\n };\n}\n\nexport class DefaultListAppLambdaFunctionsService\n implements ListAppLambdaFunctionsService.Interface\n{\n constructor(\n private pulumiExportService: PulumiExportService.Interface,\n private loggerService: LoggerService.Interface\n ) {}\n\n async execute(app: AppModel, params?: ListAppLambdaFunctionsService.Params) {\n const stackExport = await this.pulumiExportService.execute<ExpectedStackExport>(app);\n\n if (!stackExport) {\n // If no stack export is found, return an empty array. This is a valid scenario.\n // For example, watching the Admin app locally, but not deploying it.\n return {\n list: [],\n meta: {\n count: 0,\n totalCount: 0\n }\n };\n }\n\n // If an app is not deployed, resources will not exist.\n const resources = stackExport.deployment?.resources ?? [];\n\n const allFunctionsList = resources\n .filter(r => r.type === \"aws:lambda/function:Function\")\n // We don't need to watch the authorizer function.\n .filter(resource => {\n const isAuthorizerFunction = resource.inputs.name.includes(\n \"watch-command-iot-authorizer\"\n );\n return !isAuthorizerFunction;\n });\n\n let filteredFunctionsList = allFunctionsList\n // First, this filter ensures that Lambda@Edge functions are excluded. Second,\n // it also ensures a function is filtered out if a `pulumi refresh` was called.\n // This is because, when called, the paths in Pulumi state file disappear, and\n // we can't determine the path to the handler. Probably needs revisiting. 🤦♂️\n .filter(resource => {\n return \".\" in resource.inputs.code.assets;\n })\n .map(resource => {\n const fnName = resource.inputs.name;\n const handlerBuildFolderPath = resource.inputs.code.assets[\".\"].path;\n\n const handlerPath = path.join(handlerBuildFolderPath, \"handler.mjs\");\n return {\n name: fnName,\n path: handlerPath\n };\n });\n\n if (params?.whitelist?.length) {\n const functionNamesToMatch = Array.isArray(params.whitelist)\n ? params.whitelist\n : [params.whitelist];\n\n // `functionNamesToWatch` is an array of glob patterns, which denote which functions to watch.\n filteredFunctionsList = filteredFunctionsList.filter(fn => {\n return functionNamesToMatch.some(pattern => {\n if (pattern.includes(\"*\")) {\n return minimatch(fn.name, pattern);\n }\n\n return fn.name.includes(pattern);\n });\n });\n } else {\n // We've hardcoded this filtering here just because of lack of time.\n // With v5, these \"presets\" were located within `webiny.application.ts` files.\n if (app.name === \"api\") {\n filteredFunctionsList = filteredFunctionsList.filter(fn => {\n return fn.name.includes(\"graphql\");\n });\n }\n }\n\n return {\n list: filteredFunctionsList,\n meta: { count: filteredFunctionsList.length, totalCount: allFunctionsList.length }\n };\n }\n}\n\nexport const listAppLambdaFunctionsService = createImplementation({\n abstraction: ListAppLambdaFunctionsService,\n implementation: DefaultListAppLambdaFunctionsService,\n dependencies: [PulumiExportService, LoggerService]\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type IProjectModel } from "../abstractions/models/index.js";
|
|
2
|
+
export declare class ExtensionSrcResolver {
|
|
3
|
+
private static pathMappings;
|
|
4
|
+
/**
|
|
5
|
+
* Import a module from a given file path.
|
|
6
|
+
* - If path starts with "/extensions/", it resolves from project root
|
|
7
|
+
* - If path matches tsconfig path alias (e.g., "@/*"), it resolves using tsconfig
|
|
8
|
+
* - Otherwise, treats path as absolute
|
|
9
|
+
* Returns the default export or named export matching the filename.
|
|
10
|
+
*/
|
|
11
|
+
static importFromPath(filePath: string, project: IProjectModel): Promise<any>;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a file path to an absolute path.
|
|
14
|
+
* - If path starts with "/extensions/", it resolves from project root
|
|
15
|
+
* - If path matches tsconfig path alias (e.g., "@/*"), it resolves using tsconfig
|
|
16
|
+
* - Otherwise, treats path as absolute
|
|
17
|
+
* Returns the absolute path without importing.
|
|
18
|
+
*/
|
|
19
|
+
static resolvePath(filePath: string, project: IProjectModel): string;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a file exists at the given path.
|
|
22
|
+
* Resolves the path using the same logic as resolvePath before checking.
|
|
23
|
+
* - If path starts with "/extensions/", it resolves from project root
|
|
24
|
+
* - If path matches tsconfig path alias (e.g., "@/*"), it resolves using tsconfig
|
|
25
|
+
* - Otherwise, treats path as absolute
|
|
26
|
+
* Returns true if the file exists, false otherwise.
|
|
27
|
+
*/
|
|
28
|
+
static existsSync(filePath: string, project: IProjectModel): boolean;
|
|
29
|
+
private static resolvePathAlias;
|
|
30
|
+
private static loadPathMappings;
|
|
31
|
+
private static matchPattern;
|
|
32
|
+
private static replacePlaceholder;
|
|
33
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { getTsconfig } from "get-tsconfig";
|
|
4
|
+
export class ExtensionSrcResolver {
|
|
5
|
+
static pathMappings = null;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Import a module from a given file path.
|
|
9
|
+
* - If path starts with "/extensions/", it resolves from project root
|
|
10
|
+
* - If path matches tsconfig path alias (e.g., "@/*"), it resolves using tsconfig
|
|
11
|
+
* - Otherwise, treats path as absolute
|
|
12
|
+
* Returns the default export or named export matching the filename.
|
|
13
|
+
*/
|
|
14
|
+
static async importFromPath(filePath, project) {
|
|
15
|
+
const importPath = this.resolvePath(filePath, project);
|
|
16
|
+
const exportName = path.basename(filePath).replace(path.extname(filePath), "");
|
|
17
|
+
const importedModule = await import(importPath);
|
|
18
|
+
|
|
19
|
+
// Support both default and named exports.
|
|
20
|
+
// Check for 'default' property existence rather than truthiness.
|
|
21
|
+
return "default" in importedModule && importedModule.default || importedModule[exportName];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a file path to an absolute path.
|
|
26
|
+
* - If path starts with "/extensions/", it resolves from project root
|
|
27
|
+
* - If path matches tsconfig path alias (e.g., "@/*"), it resolves using tsconfig
|
|
28
|
+
* - Otherwise, treats path as absolute
|
|
29
|
+
* Returns the absolute path without importing.
|
|
30
|
+
*/
|
|
31
|
+
static resolvePath(filePath, project) {
|
|
32
|
+
if (filePath.startsWith("/extensions/")) {
|
|
33
|
+
// Resolve from project root.
|
|
34
|
+
return project.paths.rootFolder.join(filePath).toString();
|
|
35
|
+
} else {
|
|
36
|
+
// Try to resolve using tsconfig path aliases.
|
|
37
|
+
const resolved = this.resolvePathAlias(filePath, project);
|
|
38
|
+
if (resolved) {
|
|
39
|
+
return resolved;
|
|
40
|
+
} else {
|
|
41
|
+
// Treat as absolute path.
|
|
42
|
+
return filePath;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if a file exists at the given path.
|
|
49
|
+
* Resolves the path using the same logic as resolvePath before checking.
|
|
50
|
+
* - If path starts with "/extensions/", it resolves from project root
|
|
51
|
+
* - If path matches tsconfig path alias (e.g., "@/*"), it resolves using tsconfig
|
|
52
|
+
* - Otherwise, treats path as absolute
|
|
53
|
+
* Returns true if the file exists, false otherwise.
|
|
54
|
+
*/
|
|
55
|
+
static existsSync(filePath, project) {
|
|
56
|
+
const absolutePath = this.resolvePath(filePath, project);
|
|
57
|
+
return fs.existsSync(absolutePath);
|
|
58
|
+
}
|
|
59
|
+
static resolvePathAlias(filePath, project) {
|
|
60
|
+
const projectRoot = project.paths.rootFolder.toString();
|
|
61
|
+
|
|
62
|
+
// Load path mappings from tsconfig if not already cached.
|
|
63
|
+
if (this.pathMappings === null) {
|
|
64
|
+
this.loadPathMappings(project);
|
|
65
|
+
}
|
|
66
|
+
if (!this.pathMappings) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Try to match against each path pattern.
|
|
71
|
+
for (const [pattern, targets] of Object.entries(this.pathMappings)) {
|
|
72
|
+
const match = this.matchPattern(filePath, pattern);
|
|
73
|
+
if (match !== null) {
|
|
74
|
+
// Use the first mapping.
|
|
75
|
+
const target = targets[0];
|
|
76
|
+
const resolvedPath = this.replacePlaceholder(target, match);
|
|
77
|
+
return path.resolve(projectRoot, resolvedPath);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
static loadPathMappings(project) {
|
|
83
|
+
const tsConfigPath = project.paths.tsConfigFile.toString();
|
|
84
|
+
try {
|
|
85
|
+
// Use get-tsconfig to parse tsconfig with extends resolution.
|
|
86
|
+
const tsconfig = getTsconfig(tsConfigPath);
|
|
87
|
+
if (tsconfig?.config.compilerOptions?.paths) {
|
|
88
|
+
this.pathMappings = tsconfig.config.compilerOptions.paths;
|
|
89
|
+
} else {
|
|
90
|
+
this.pathMappings = {};
|
|
91
|
+
}
|
|
92
|
+
} catch {
|
|
93
|
+
// Ignore tsconfig parsing errors.
|
|
94
|
+
this.pathMappings = {};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
static matchPattern(importPath, pattern) {
|
|
98
|
+
// Handle wildcard patterns like "@/*" or "@extensions/*".
|
|
99
|
+
if (pattern.endsWith("/*")) {
|
|
100
|
+
const prefix = pattern.slice(0, -2);
|
|
101
|
+
// Only match if there's a slash after the prefix.
|
|
102
|
+
if (importPath.startsWith(prefix + "/")) {
|
|
103
|
+
return importPath.slice(prefix.length + 1);
|
|
104
|
+
}
|
|
105
|
+
} else if (pattern === importPath) {
|
|
106
|
+
return "";
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
static replacePlaceholder(mapping, match) {
|
|
111
|
+
// Replace wildcard with the matched part.
|
|
112
|
+
if (mapping.endsWith("/*")) {
|
|
113
|
+
return mapping.slice(0, -2) + "/" + match;
|
|
114
|
+
}
|
|
115
|
+
return mapping;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//# sourceMappingURL=ExtensionSrcResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["path","fs","getTsconfig","ExtensionSrcResolver","pathMappings","importFromPath","filePath","project","importPath","resolvePath","exportName","basename","replace","extname","importedModule","default","startsWith","paths","rootFolder","join","toString","resolved","resolvePathAlias","existsSync","absolutePath","projectRoot","loadPathMappings","pattern","targets","Object","entries","match","matchPattern","target","resolvedPath","replacePlaceholder","resolve","tsConfigPath","tsConfigFile","tsconfig","config","compilerOptions","endsWith","prefix","slice","length","mapping"],"sources":["ExtensionSrcResolver.ts"],"sourcesContent":["import path from \"path\";\nimport fs from \"fs\";\nimport { getTsconfig } from \"get-tsconfig\";\nimport { type IProjectModel } from \"~/abstractions/models/index.js\";\n\nexport class ExtensionSrcResolver {\n private static pathMappings: { [key: string]: string[] } | null = null;\n\n /**\n * Import a module from a given file path.\n * - If path starts with \"/extensions/\", it resolves from project root\n * - If path matches tsconfig path alias (e.g., \"@/*\"), it resolves using tsconfig\n * - Otherwise, treats path as absolute\n * Returns the default export or named export matching the filename.\n */\n static async importFromPath(filePath: string, project: IProjectModel) {\n const importPath = this.resolvePath(filePath, project);\n const exportName = path.basename(filePath).replace(path.extname(filePath), \"\");\n\n const importedModule = await import(importPath);\n\n // Support both default and named exports.\n // Check for 'default' property existence rather than truthiness.\n return (\n (\"default\" in importedModule && importedModule.default) || importedModule[exportName]\n );\n }\n\n /**\n * Resolve a file path to an absolute path.\n * - If path starts with \"/extensions/\", it resolves from project root\n * - If path matches tsconfig path alias (e.g., \"@/*\"), it resolves using tsconfig\n * - Otherwise, treats path as absolute\n * Returns the absolute path without importing.\n */\n static resolvePath(filePath: string, project: IProjectModel): string {\n if (filePath.startsWith(\"/extensions/\")) {\n // Resolve from project root.\n return project.paths.rootFolder.join(filePath).toString();\n } else {\n // Try to resolve using tsconfig path aliases.\n const resolved = this.resolvePathAlias(filePath, project);\n if (resolved) {\n return resolved;\n } else {\n // Treat as absolute path.\n return filePath;\n }\n }\n }\n\n /**\n * Check if a file exists at the given path.\n * Resolves the path using the same logic as resolvePath before checking.\n * - If path starts with \"/extensions/\", it resolves from project root\n * - If path matches tsconfig path alias (e.g., \"@/*\"), it resolves using tsconfig\n * - Otherwise, treats path as absolute\n * Returns true if the file exists, false otherwise.\n */\n static existsSync(filePath: string, project: IProjectModel): boolean {\n const absolutePath = this.resolvePath(filePath, project);\n return fs.existsSync(absolutePath);\n }\n\n private static resolvePathAlias(filePath: string, project: IProjectModel): string | null {\n const projectRoot = project.paths.rootFolder.toString();\n\n // Load path mappings from tsconfig if not already cached.\n if (this.pathMappings === null) {\n this.loadPathMappings(project);\n }\n\n if (!this.pathMappings) {\n return null;\n }\n\n // Try to match against each path pattern.\n for (const [pattern, targets] of Object.entries(this.pathMappings)) {\n const match = this.matchPattern(filePath, pattern);\n if (match !== null) {\n // Use the first mapping.\n const target = targets[0];\n const resolvedPath = this.replacePlaceholder(target, match);\n return path.resolve(projectRoot, resolvedPath);\n }\n }\n\n return null;\n }\n\n private static loadPathMappings(project: IProjectModel): void {\n const tsConfigPath = project.paths.tsConfigFile.toString();\n\n try {\n // Use get-tsconfig to parse tsconfig with extends resolution.\n const tsconfig = getTsconfig(tsConfigPath);\n\n if (tsconfig?.config.compilerOptions?.paths) {\n this.pathMappings = tsconfig.config.compilerOptions.paths;\n } else {\n this.pathMappings = {};\n }\n } catch {\n // Ignore tsconfig parsing errors.\n this.pathMappings = {};\n }\n }\n\n private static matchPattern(importPath: string, pattern: string): string | null {\n // Handle wildcard patterns like \"@/*\" or \"@extensions/*\".\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -2);\n // Only match if there's a slash after the prefix.\n if (importPath.startsWith(prefix + \"/\")) {\n return importPath.slice(prefix.length + 1);\n }\n } else if (pattern === importPath) {\n return \"\";\n }\n\n return null;\n }\n\n private static replacePlaceholder(mapping: string, match: string): string {\n // Replace wildcard with the matched part.\n if (mapping.endsWith(\"/*\")) {\n return mapping.slice(0, -2) + \"/\" + match;\n }\n return mapping;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
package/utils/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export * from "./createPathResolver.js";
|
|
|
3
3
|
export * from "./getRandomColorForString.js";
|
|
4
4
|
export * from "./getStackName.js";
|
|
5
5
|
export * from "./getTemplatesFolderPath.js";
|
|
6
|
-
export * from "./
|
|
6
|
+
export * from "./ExtensionSrcResolver.js";
|
|
7
7
|
export * from "./isValidRegionName.js";
|
|
8
8
|
export * from "./isValidVariantName.js";
|
|
9
9
|
export * from "./measureDuration.js";
|
package/utils/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export * from "./createPathResolver.js";
|
|
|
3
3
|
export * from "./getRandomColorForString.js";
|
|
4
4
|
export * from "./getStackName.js";
|
|
5
5
|
export * from "./getTemplatesFolderPath.js";
|
|
6
|
-
export * from "./
|
|
6
|
+
export * from "./ExtensionSrcResolver.js";
|
|
7
7
|
export * from "./isValidRegionName.js";
|
|
8
8
|
export * from "./isValidVariantName.js";
|
|
9
9
|
export * from "./measureDuration.js";
|
package/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./constants.js\";\nexport * from \"./createPathResolver.js\";\nexport * from \"./getRandomColorForString.js\";\nexport * from \"./getStackName.js\";\nexport * from \"./getTemplatesFolderPath.js\";\nexport * from \"./
|
|
1
|
+
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./constants.js\";\nexport * from \"./createPathResolver.js\";\nexport * from \"./getRandomColorForString.js\";\nexport * from \"./getStackName.js\";\nexport * from \"./getTemplatesFolderPath.js\";\nexport * from \"./ExtensionSrcResolver.js\";\nexport * from \"./isValidRegionName.js\";\nexport * from \"./isValidVariantName.js\";\nexport * from \"./measureDuration.js\";\nexport * from \"./requireConfig.js\";\nexport * from \"./projectSdkContext.js\";\nexport * from \"./registerExtension.js\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type IProjectModel } from "../abstractions/models/index.js";
|
|
2
|
-
export declare class ImplPathResolver {
|
|
3
|
-
/**
|
|
4
|
-
* Import a module from a given file path.
|
|
5
|
-
* - If path starts with "/extensions/", it resolves from project root
|
|
6
|
-
* - Otherwise, treats path as absolute
|
|
7
|
-
* Returns the default export or named export matching the filename.
|
|
8
|
-
*/
|
|
9
|
-
static importFromPath(filePath: string, project: IProjectModel): Promise<any>;
|
|
10
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
export class ImplPathResolver {
|
|
3
|
-
/**
|
|
4
|
-
* Import a module from a given file path.
|
|
5
|
-
* - If path starts with "/extensions/", it resolves from project root
|
|
6
|
-
* - Otherwise, treats path as absolute
|
|
7
|
-
* Returns the default export or named export matching the filename.
|
|
8
|
-
*/
|
|
9
|
-
static async importFromPath(filePath, project) {
|
|
10
|
-
let importPath;
|
|
11
|
-
if (filePath.startsWith("/extensions/")) {
|
|
12
|
-
// Resolve from project root.
|
|
13
|
-
importPath = project.paths.rootFolder.join(filePath).toString();
|
|
14
|
-
} else {
|
|
15
|
-
// Treat as absolute path.
|
|
16
|
-
importPath = filePath;
|
|
17
|
-
}
|
|
18
|
-
const exportName = path.basename(filePath).replace(path.extname(filePath), "");
|
|
19
|
-
const importedModule = await import(importPath);
|
|
20
|
-
|
|
21
|
-
// Support both default and named exports.
|
|
22
|
-
// Check for 'default' property existence rather than truthiness.
|
|
23
|
-
return "default" in importedModule && importedModule.default || importedModule[exportName];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
//# sourceMappingURL=ImplPathResolver.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["path","ImplPathResolver","importFromPath","filePath","project","importPath","startsWith","paths","rootFolder","join","toString","exportName","basename","replace","extname","importedModule","default"],"sources":["ImplPathResolver.ts"],"sourcesContent":["import path from \"path\";\nimport { type IProjectModel } from \"~/abstractions/models/index.js\";\n\nexport class ImplPathResolver {\n /**\n * Import a module from a given file path.\n * - If path starts with \"/extensions/\", it resolves from project root\n * - Otherwise, treats path as absolute\n * Returns the default export or named export matching the filename.\n */\n static async importFromPath(filePath: string, project: IProjectModel) {\n let importPath: string;\n if (filePath.startsWith(\"/extensions/\")) {\n // Resolve from project root.\n importPath = project.paths.rootFolder.join(filePath).toString();\n } else {\n // Treat as absolute path.\n importPath = filePath;\n }\n\n const exportName = path.basename(filePath).replace(path.extname(filePath), \"\");\n\n const importedModule = await import(importPath);\n\n // Support both default and named exports.\n // Check for 'default' property existence rather than truthiness.\n return (\n (\"default\" in importedModule && importedModule.default) || importedModule[exportName]\n );\n }\n}\n"],"mappings":"AAAA,OAAOA,IAAI,MAAM,MAAM;AAGvB,OAAO,MAAMC,gBAAgB,CAAC;EAC1B;AACJ;AACA;AACA;AACA;AACA;EACI,aAAaC,cAAcA,CAACC,QAAgB,EAAEC,OAAsB,EAAE;IAClE,IAAIC,UAAkB;IACtB,IAAIF,QAAQ,CAACG,UAAU,CAAC,cAAc,CAAC,EAAE;MACrC;MACAD,UAAU,GAAGD,OAAO,CAACG,KAAK,CAACC,UAAU,CAACC,IAAI,CAACN,QAAQ,CAAC,CAACO,QAAQ,CAAC,CAAC;IACnE,CAAC,MAAM;MACH;MACAL,UAAU,GAAGF,QAAQ;IACzB;IAEA,MAAMQ,UAAU,GAAGX,IAAI,CAACY,QAAQ,CAACT,QAAQ,CAAC,CAACU,OAAO,CAACb,IAAI,CAACc,OAAO,CAACX,QAAQ,CAAC,EAAE,EAAE,CAAC;IAE9E,MAAMY,cAAc,GAAG,MAAM,MAAM,CAACV,UAAU,CAAC;;IAE/C;IACA;IACA,OACK,SAAS,IAAIU,cAAc,IAAIA,cAAc,CAACC,OAAO,IAAKD,cAAc,CAACJ,UAAU,CAAC;EAE7F;AACJ","ignoreList":[]}
|